From de5e2fa6626c3f9f6878f44c85bfec9fb2cdc7cb Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Mon, 20 Oct 2025 10:54:16 +0200 Subject: [PATCH 01/76] Doku Benutzerverwaltung --- .../Doku_Benutzerverwaltung.md | 192 ++++++++++++++++++ web/Benutzerverwaltung/Theme-Bereiche.png | Bin 0 -> 109393 bytes 2 files changed, 192 insertions(+) create mode 100644 web/Benutzerverwaltung/Doku_Benutzerverwaltung.md create mode 100644 web/Benutzerverwaltung/Theme-Bereiche.png diff --git a/web/Benutzerverwaltung/Doku_Benutzerverwaltung.md b/web/Benutzerverwaltung/Doku_Benutzerverwaltung.md new file mode 100644 index 0000000000..bf5b4dd180 --- /dev/null +++ b/web/Benutzerverwaltung/Doku_Benutzerverwaltung.md @@ -0,0 +1,192 @@ +# Benutzerverwaltung + +## 1. Einleitung + +Die software2 soll um eine Benutzerverwaltung erweitert werden. Dabei sollen die jeweiligen Rechte möglichst feingliedrig vergeben werden können. + +Der einfachste Anwendungsfall ist der, dass die komplette Bedienung und Konfiguration nur nach erfolgreicher Anmeldung möglich ist. Nächste Variante ist, dass eine Bedienung zwar möglich, die Einstellungen jedoch ohne Anmeldung nicht zugänglich sind. Komplexere Fälle treten bei WEGs auf, wo der einzelne Zugriff auf Ladepunkte, Fahrzeuge und weitere Geräte/Komponenten zu regeln ist. + +Die genauen Anforderungen und abzudeckende Einsatzfälle sind noch festzulegen. Abhängig von diesen Festlegungen ist schließlich die genaue technische Umsetzung zu planen, daher werden hier lediglich sinnvolle Leitlinien kurz vorgestellt. + +Zusätzlich zu der reinen Benutzerverwaltung gibt es noch die Anforderung, dass die jetzigen Einstellungen optisch an das Koala Theme angepasst werden. Dabei sollen Synergieeffekte genutzt werden, sodass ein "Baukastensystem" aus kleinen Elementen ("Components") entsteht, welche sowohl in den Einstellungen als auch dem Koala Theme verwendet werden. So kann auch langfristig ein einheitliches Erscheinungsbild garantiert werden, ohne dass Elemente mehrfach gepflegt werden müssen. + +## 2. Aktueller Stand der software2 im Hinblick auf die Benutzeroberflächen + +### 2.1 Konfiguration des Webservers + +Die Konfiguration des Apache2 Webservers ist so eingestellt, dass das Wurzelverzeichnis (zu erreichen über `http(s)://\/`) auf `/var/www/html/` zeigt und somit eine Ebene über dem openWB-Verzeichnis und außerhalb des core Repository liegt. Es wird ein Zugriff über `http` und `https` erlaubt. Der verschlüsselte Zugriff wird mit einem selbst signierten Zertifikat abgesichert. Eine automatische Weiterleitung von `http` nach `https` gibt es nicht. + +Für die verschiedenen Benutzeroberflächen wird die Verbindung zum MQTT-Broker ebenfalls vom Webserver bereitgestellt. Der Vorteil im Vergleich mit dem separaten Port der Version 1.9.x ist, dass weniger bis keine Probleme mit eventuell blockierten Ports auftreten. Der Zugriffspunkt für die Websocket-Verbindung ist `http(s)://\/ws`. Zusätzlich wird derzeit noch aus Kompatibilitätsgründen `http(s)://\/mqtt` eingerichtet. Die Verbindung zwischen Webserver und Broker ist unverschlüsselt, da alles unter "localhost" abläuft. Die Weiterleitung des Websockets erfolgt auf Port 9001, wo der öffentlich erreichbare Mosquitto Broker läuft. + +Die HTTP-API wird über einen separaten Port (8443) ausschließlich verschlüsselt bereitgestellt. Die API selber ruft die Daten vom öffentlichen Broker auf Port 1883 ab. Auch hier wird auf Verschlüsselung verzichtet, da die Kommunikation komplett über "localhost" läuft. + +Bei einer Pro+ wird auf Port 8080 ein Proxy auf die Webseite der Pro+ geöffnet. Diese beiden Ports sind komplett unabhängig von den Benutzeroberflächen und sind hier nur der Vollständigkeit halber aufgeführt. + +### 2.2 Benutzeroberflächen + +In der jetzigen Struktur sind mehrere separate Web-Projekte vorhanden: + +1. Primärer Einstiegspunkt (Weiterleitung): `http(s)://\/` +2. Sekundärer Einstiegspunkt (Weiterleitung): `http(s)://\/openWB/` +3. Einstiegspunkt der Weboberfläche ("Theme-Wrapper"): `http(s)://\/openWB/web/` +4. Einzelne Web-Themes: `http(s)://\/openWB/web/themes/\/` +5. Einstiegspunkt des Displays ("Display-Wrapper"): `http(s)://\/openWB/web/display/` +6. Einzelne Display-Themes: `http(s)://\/openWB/web/display/themes/\/` +7. Einstellungen: `http(s)://\/openWB/web/settings/` +8. Wartungsseite mit Systeminformationen: `http(s)://\/openWB/web/maintenance/systeminfo.html` + +Die Weiterleitungen unter 1. und 2. führen den Browser lediglich zu 3. Dabei ist zu beachten, dass 1. **nicht** im openWB-Verzeichnis liegt und somit auch **nicht im core Repository** vorhanden ist. Die Weiterleitung unter 2. wird in dem Installationsskript nach 1. kopiert, um das Problem zu lösen. + +Der Theme-Wrapper (3.) ist der normale Einstiegspunkt für den Anwender. Es wird eine Verbindung zum Broker hergestellt, die Konfiguration des Themes empfangen und dann der Browser auf das passende Theme zu 4. weitergeleitet. Der komplette Code ist ohne ein Framework umgesetzt und teilweise aus 1.9.x übernommen und erweitert worden. Die Verbindung zum Broker richtet sich nach der aktuellen URL im Browser und wird bei HTTP unverschlüsselt, bei HTTPs verschlüsselt hergestellt. + +Die einzelnen Themes (4.) arbeiten komplett unabhängig von den anderen Projekten. Das bedeutet auch, dass wichtige Links z.B. zu dem Status oder den Einstellungen in jedem Theme selbst umgesetzt werden müssen. Die Verbindung zum Broker richtet sich nach der aktuellen URL im Browser und wird bei HTTP unverschlüsselt, bei HTTPs verschlüsselt hergestellt. + +Analog zu dem Theme-Wrapper funktioniert der Display-Wrapper (5.). Ein wichtiger Unterschied ist jedoch, dass keine reine Weiterleitung erfolgt, sondern das konfigurierte Display-Theme in einem Unterfenster ("iframe" mit URL zu 6.) angezeigt wird. So bleibt der Wrapper im Hintergrund aktiv und kann auf relevante Änderungen der Konfiguration (z.B. anderes Display-Theme ausgewählt) reagieren. Dieser Code hat sehr viele Überschneidungen mit dem Theme-Wrapper und wurde ebenfalls aus der 1.9.x migriert.Die Verbindung zum Broker richtet sich nach der aktuellen URL im Browser und wird bei HTTP unverschlüsselt, bei HTTPs verschlüsselt hergestellt. Das ist notwendig, da die Darstellung auch von anderen Geräten angesprochen werden kann. + +Die Einstellungen (7.) sind rein optisch eine Portierung aus 1.9.x mit Anpassung auf Vue.JS als Framework. Es wird weiterhin auf Bootstrap als Layout-System gesetzt, jedoch in der veralteten Version 4.6. Das bringt einige Einschränkungen mit sich, die jedoch nur durch eine grundlegende Überarbeitung des kompletten Projektes beseitigt werden können. + +Die relativ neue Wartungsseite (8.) wurde absichtlich komplett unabhängig von anderen Web-Projekten und dem Backend erstellt. Hier war "KISS" dir Voraussetzung, um auch bei Problemen mit anderen Diensten noch Daten anzeigen zu können. So muss lediglich der Webserver erreichbar sein, um die Seite aufrufen zu können. Erste Erfahrungen haben aber gezeigt, dass teilweise der Datenabruf nicht mehr funktioniert, wenn das System durch andere Prozesse ausgelastet ist. + +#### 2.2.1 Web Themes + +##### 2.2.1.1 Altes Standard Theme + +Das "alte" Standard-Theme ist im wesentlichen eine Portierung von Code aus der 1.9.x. Sämtlicher Code ist handgeschrieben und es werden keine Frameworks verwendet. Anpassungen sind daher immer mit relativ viel Aufwand verbunden. Auch hier kommt die veraltete Bootstrap Version 4.6 zum Einsatz. + +Die Verbindung zum Broker richtet sich nach der aktuellen URL im Browser und wird bei HTTP unverschlüsselt, bei HTTPs verschlüsselt hergestellt. + +##### 2.2.1.2 Koala Theme + +Das Koala Theme wurde von Beginn an mit aktueller Technik entwickelt. Basis ist das Quasar Framework. Dies erlaubt es z.B. aus einer Codebasis nicht nur Webseiten, sondern auch Apps für Android und iOS oder native Anwendungen für MAC/Windows/Linux zu erstellen. + +Im Gegensatz zu allen anderen Web-Projekten wird im Code TypeScript anstatt reines JavaScript verwendet. Dadurch werden wesentlich mehr Hilfsfunktionen in der Entwicklungsumgebung nutzbar, welche letztendlich den Code stabiler machen. + +Die Verbindung zum Broker richtet sich nach der aktuellen URL im Browser und wird bei HTTP unverschlüsselt, bei HTTPs verschlüsselt hergestellt. + +##### 2.2.1.3 Colors Theme + +Das Colors Theme wird von Claus "electron" aus der Community gepflegt. Wir achten jedoch darauf, dass die Verbindung zum Broker und andere Standards analog zu den offiziellen Themes eingehalten werden. + +Die Verbindung zum Broker richtet sich nach der aktuellen URL im Browser und wird bei HTTP unverschlüsselt, bei HTTPs verschlüsselt hergestellt. + +#### 2.2.2 Display Themes + +##### 2.2.2.1 Cards Display Theme + +Das Cards Theme basiert auf einer (inzwischen älteren) Version von "Inkline", einer auf Vue.js basierenden Oberflächen-Bibliothek (vergleichbar mit Bootstrap). + +Die Verbindung zum Broker richtet sich nach der aktuellen URL im Browser und wird bei HTTP unverschlüsselt, bei HTTPs verschlüsselt hergestellt. + +##### 2.2.2.2 Colors Display Theme + +Das Colors Theme wird von Claus "electron" aus der Community gepflegt. Wir achten jedoch darauf, dass die Verbindung zum Broker und andere Standards analog zu den offiziellen Themes eingehalten werden. + +Die Verbindung zum Broker richtet sich nach der aktuellen URL im Browser und wird bei HTTP unverschlüsselt, bei HTTPs verschlüsselt hergestellt. + +## 3. Schnittstellen Back-/Frontend und Drittanwendungen + +### 3.1 MQTT + +Auf einer openWB laufen immer zwei Mosquitto Server. Einer ist nur über "localhost", also lokal laufenden Prozessen, zu erreichen. Der "externe" Server ist über eine Brücke auf Port 1884 an den lokalen gebunden. Sämtliche externen Zugriffe erfolgen immer auf den externen Broker. + +#### 3.1.1 Lokaler Broker + +Der lokale Broker stellt den Port 1886 (Protokoll "mqtt") ausschließlich auf "localhost" zur Verfügung. Über diesen Port sind sämtliche Topics ohne Zugangsschutz oder -regeln (ACL) les- und schreibbar. Diese Instanz wird vom Backend verwendet. + +Zusätzlich wird eine Brücke zum externen Broker aufgebaut. Für diese Brücke ist dediziert festgelegt, welche Topics in welche Richtung übertragen werden. + +Wenn eine weitere Brücke oder die openWB Cloud eingerichtet werden, stellt der lokale Broker auch diese Verbindungen her. Die erlaubten Topics sind in der jeweiligen Konfiguration der Brücke geregelt. + +#### 3.1.2 Externer Broker + +Der externe Broker stellt die Schnittstelle für sämtliche Benutzeroberflächen dar und enthält nur einen Teil der Daten des lokalen Brokers. + +Über Port 1884 (mqtt, nur "localhost") kann sich der lokale Broker verbinden. + +Websocket-Verbindungen können über die Ports 9001 (unverschlüsselt) und 9002 (verschlüsselt) hergestellt werden. Beide Ports erfordern keine Authentifizierung ("allow_anonymous = true") und verwenden eine ACL-Datei, um Beschränkungen im Hinblick auf lesen und schreiben zu setzen. + +Analog zu den Websocket-Ports ist auch ein Zugang über das "mqtt" Protokoll (1883 unverschlüsselt, 8883 verschlüsselt) möglich. Die Sicherheitseinstellungen der beiden Ports sind analog zu den Websockets konfiguriert. + +### 3.2 HTTP-API + +Die HTTP-API auf Port 8443 kann nur über eine verschlüsselte Verbindung angesprochen werden. Es spricht demnach nichts dagegen, Anfragen auch in Hinsicht auf eine Authentifizierung zu erweitern. Die API selbst verwendet dann die übergebenen Anmeldedaten bei der Verbindung zum Broker. So muss die API nicht auch noch angepasst und abgesichert werden. + +### 3.3 Modbus + +Die Modbus Schnittstelle auf Port 1502 kann optional aktiviert werden, wenn eine openWB als secondary betrieben wird. Modbus/TCP unterstützt keine Authentifizierung und sollte daher in so einem Fall deaktiviert bleiben. Eventuell könnte die übergeordnete primary prüfen, ob Modbus auf den secondaries aktiviert ist und ggf. warnen oder die Schnittstelle eigenmächtig deaktivieren. + +## 4. Leitlinien zur Entwicklung einer Umsetzung + +### 4.1 Absicherung der openWB + +#### 4.1.1 Grundlegende Voraussetzungen + +Die hier aufgeführten Unterpunkte sind zwar Voraussetzung für eine Benutzerverwaltung, könnten aber, um die Umstellung etwas zu entzerren, bereits im Vorfeld unabhängig umgesetzt werden. + +##### 4.1.1.1 Verschlüsselter Zugang + +Damit Anmeldedaten nicht über das Netzwerk mitgelesen werden können, müssen sämtliche unverschlüsselten externen Zugänge (Broker, Webserver, APIs) abgeschaltet werden. Der Zugang über "localhost" (z.B. zum Broker) kann weiterhin unverschlüsselt erfolgen, falls dies noch benötigt wird und umsetzbar ist. + +##### 4.1.1.2 Zertifikatsmanagement + +Die verwendeten SSL-Zertifikate sind selbst signiert und können unter Umständen bei einigen Clients für Probleme sorgen, daher sollte das verwendete Zertifikat änderbar sein. Es muss eine Möglichkeit geben, den öffentlichen Teil des Zertifikates herunterzuladen, um ihn in einem Client eintragen zu können. Zusätzlich muss es die Möglichkeit geben, ein eigenes Zertifikat für den kompletten SSL-Traffic zu hinterlegen. Das beschriebene Zertifikatsmanagement wird vermutlich besonders bei größeren Installationen von Bedeutung sein. + +##### 4.1.1.3 Hostname und IP anpassbar + +Im Zusammenhang mit Zertifikaten ist es wichtig, dass der Hostname zum Zertifikat passt. Ebenfalls kann eine IP Teil des Zertifikats sein. Folglich sollten beide Einstellungen anpassbar sein. + +Die IP des "Plug'n'Play" Netzwerkes (Standard `192.168.193.250`) sollte in diesem Zuge ebenfalls konfigurierbar umgesetzt werden, damit es nicht potentiell zu Konflikten kommt bzw. ein Adresskonflikt durch Anpassung behoben werden kann. + +#### 4.1.2 Rechtemanagement + +Für den Mosquitto Broker gibt es das [Dynamic Security Plugin](https://mosquitto.org/documentation/dynamic-security/). Dieses erlaubt eine sehr feine Rechteverwaltung auf Basis von Clients, Rollen und ACLs. Die komplette Konfiguration erfolgt ebenfalls zur Laufzeit per MQTT. Es wird empfohlen, dafür Programm `mosquitto_ctrl` auf der Kommandozeile zu verwenden, es ist aber auch möglich, Einstellungen direkt über Topics zu setzen. + +### 4.2 Startseite + +Wenn die openWB im Browser aufgerufen wird, sollte als erstes eine Anmeldemaske erscheinen. So ist sichergestellt, dass unbefugte keine Möglichkeit haben, Einstellungen zu verändern und in eventuell andere Ladevorgänge einzugreifen. Das bedeutet auch, dass mindestens die URL `http(s)://\/openWB/web/` durch die Anmeldeseite abgefangen werden muss. + +Um abwärtskompatibel zu bleiben, sollte der Pfad `/openWB/web/` beibehalten werden, auch wenn er eigentlich keinen Sinn mehr macht (Überbleibsel aus 1.x). Die beiden reinen Weiterleitungen (Punkte 1. und 2. in Abschnitt 2.2) können demnach erhalten bleiben. + +### 4.3 Veralteten Code entfernen + +Der unter 2.2 aufgeführte "Theme-Wrapper" (Punkt 3.) muss im Zuge einer Benutzerverwaltung komplett überarbeitet werden, da dieser Pfad von der neuen Anmeldeseite verwendet wird (siehe 3.1). Ohne eine vorherige Anmeldung darf kein Theme angezeigt werden. Daher bietet es sich an, diese Funktionalität in das neue Projekt zu integrieren. + +### 4.4 Einheitliches Menü für alle Themes + +Oben wurde angesprochen, dass jedes Theme für die Links zu Status, Einstellungen etc. selbst verantwortlich ist. Es muss also in jedem Theme ein gewisser Anteil Code zwingend enthalten sein. Dabei stelle ich mir die Frage, ob das nicht einheitlich gelöst werden kann. + +| ![Bereiche eines Themes - Koala]() | +|:--:| +| *Abbildung 1: Die farblich markierten Bereiche im Koala Theme zeigen, welche Funktionen einheitlich umgesetzt werden sollten (grün) und welche individuell vom Theme gestaltet werden (gelb).* | + +Am Beispiel des Koala Themes habe ich in Abbildung 1 zwei Bereiche eingefärbt. Grün hinterlegt ist die Funktionalität, welche in jedem Theme aktuell selbst umgesetzt werden muss. Der gelbe Bereich hingegen ist individuell vom jeweiligen Theme gestaltet. + +Wie zu Punkt 3. in 2.2 erläutert, leitet der jetzige Theme-Wrapper den Browser direkt auf das konfigurierte Theme weiter. Außer dem Theme ist also nichts in diesem Tab aktiv. Der Display-Wrapper (Punkt 5. in 2.2) hingegen zeigt das konfigurierte Theme in einem separaten Bereich an und bleibt selber im Hintergrund aktiv. Dieses Verhalten kann auch bei den Web-Themes genutzt werden. + +Bleibt das Login-System (bzw. vormals der Wrapper) im Hintergrund aktiv, dann kann es sich auch um die Darstellung der Links kümmern. Das ausgewählte Theme wird dann im gelben Bereich eingeblendet und muss kein eigenes Menü mit Links mehr erzeugen. So ist außerdem sichergestellt, dass alle gewünschten Links in allen Themes vorhanden sind. Eine Anpassung muss dann nur einmal erfolgen, anstatt in allen Themes umgesetzt zu werden. + +### 4.5 Integration der Einstellungen + +Wenn bereits das Menü vereinheitlicht wird (3.3), dann bietet es sich auch an, die Einstellungen auch in den gelben Bereich (siehe Abbildung 1) zu integrieren. So bleibt das Bedienkonzept konsistent und es muss das Menüsystem nicht erneut in den Einstellungen umgesetzt werden. + +### 4.6 Offene Punkte + +#### 4.6.1 Betrieb ohne Anmeldung + +Zu klären wäre noch, ob optional das alte Verhalten ohne Anmeldung zu ermöglichen ist. Dazu könnte ein Benutzer angelegt werden, mit dem sich das Frontend automatisch anmeldet. Diesem Benutzer können beispielsweise Rechte eingeräumt werden, die eine rudimentäre Bedienung ermöglichen bis hin zu Vollzugriff, um weiterhin komplett ohne Anmeldung arbeiten zu können. + +#### 4.6.2 Login-System optisch an Theme anpassen + +Damit es keinen harten optischen Kontrast zwischen dem einheitlichen Menü und dem ausgewählten Theme gibt, sollte sich die Darstellung des Menüs in gewisser Weise an das Theme anpassen können. Im einfachsten Fall werden vom Theme Farben für Schrift und Hintergrund für den hellen und dunklen Modus vorgegeben. + +Weitere Möglichkeiten wie z.B. die Erweiterung des Menüs um spezifische Punkte sind ebenfalls denkbar, die Umsetzung muss jedoch noch geprüft werden. + +#### 4.6.3 Display + +Der Display-Wrapper sowie die dadurch eingebundenen Display Themes müssen sich bei aktivierter Benutzerverwaltung ebenfalls in irgendeiner Weise anmelden. Besonders bei größeren Installationen mit verschiedenen Benutzerrollen je Wallbox (z.B. WEGs), stellt dies eine größere Herausforderung dar. Eventuell könnte der Zugriff über IPs geregelt werden. + +#### 4.6.4 JSON Daten + +In manchen Situationen kann es sinnvoll sein, dass ein Client nur einen Teil eines größeren JSON Topics schreiben (ggf. auch lesen?) kann. Ein Fall wären z.B. die Lade-Profile, wo vermutlich "Priorität" und "Standard nach Abstecken" für einen normalen Anwender nicht änderbar sein sollten, andere Daten wie "Lademodus" hingegen schon. + +Es müsste evaluiert werden, welche JSON Objekte im Hinblick auf ein Rechtemanagement aufzuteilen sind und dafür eine Lösung geschaffen werden. Primäres Ziel sollte es sein, dass nicht auch noch im Backend eine Benutzerverwaltung implementiert werden muss, sondern ausschließlich mit dem Rechtemanagement im Broker gearbeitet werden kann. Ansonsten müssten zwei Bereiche immer synchron gehalten werden, was früher oder später vermutlich zu Problemen führen wird. diff --git a/web/Benutzerverwaltung/Theme-Bereiche.png b/web/Benutzerverwaltung/Theme-Bereiche.png new file mode 100644 index 0000000000000000000000000000000000000000..8179beed39e05b46bd72e59b563e26cf70aaf017 GIT binary patch literal 109393 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 QekZ9mmcLsxK)lia1 Date: Fri, 24 Oct 2025 09:00:16 +0200 Subject: [PATCH 02/76] =?UTF-8?q?Erg=C3=A4nzungen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/Benutzerverwaltung/Doku_Benutzerverwaltung.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/web/Benutzerverwaltung/Doku_Benutzerverwaltung.md b/web/Benutzerverwaltung/Doku_Benutzerverwaltung.md index bf5b4dd180..9b42bb80f3 100644 --- a/web/Benutzerverwaltung/Doku_Benutzerverwaltung.md +++ b/web/Benutzerverwaltung/Doku_Benutzerverwaltung.md @@ -139,7 +139,13 @@ Die IP des "Plug'n'Play" Netzwerkes (Standard `192.168.193.250`) sollte in diese #### 4.1.2 Rechtemanagement -Für den Mosquitto Broker gibt es das [Dynamic Security Plugin](https://mosquitto.org/documentation/dynamic-security/). Dieses erlaubt eine sehr feine Rechteverwaltung auf Basis von Clients, Rollen und ACLs. Die komplette Konfiguration erfolgt ebenfalls zur Laufzeit per MQTT. Es wird empfohlen, dafür Programm `mosquitto_ctrl` auf der Kommandozeile zu verwenden, es ist aber auch möglich, Einstellungen direkt über Topics zu setzen. +Für den Mosquitto Broker gibt es das [Dynamic Security Plugin](https://mosquitto.org/documentation/dynamic-security/). Dieses erlaubt eine sehr feine Rechteverwaltung auf Basis von Clients, Rollen und ACLs. Die komplette Konfiguration erfolgt ebenfalls zur Laufzeit per MQTT. Es wird empfohlen, dafür das Programm `mosquitto_ctrl` auf der Kommandozeile zu verwenden, es ist aber auch möglich, Einstellungen direkt über Topics zu setzen. + +#### 4.1.3 Zurücksetzen eines Kennwortes + +Es muss zwingend für den Administrator/Hauptbenutzer die Möglichkeit geben, den Zugang bei einem vergessenen Kennwort wieder herzustellen. Im einfachsten Fall könnte das, wie bei vielen Lösungen üblich, über eine hinterlegte E-Mail Adresse erfolgen, an die ein Code gesendet wird. + +Im Besten Fall lässt sich diese Option pro angelegtem Benutzer (de-)aktivieren. ### 4.2 Startseite From 95a853b57d6b3af191d51c94c2e7cb10d292373b Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Fri, 24 Oct 2025 09:00:48 +0200 Subject: [PATCH 03/76] Meeting 2025-10-23 --- .../Doku_Benutzerverwaltung.md | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/web/Benutzerverwaltung/Doku_Benutzerverwaltung.md b/web/Benutzerverwaltung/Doku_Benutzerverwaltung.md index 9b42bb80f3..8973363d59 100644 --- a/web/Benutzerverwaltung/Doku_Benutzerverwaltung.md +++ b/web/Benutzerverwaltung/Doku_Benutzerverwaltung.md @@ -196,3 +196,51 @@ Der Display-Wrapper sowie die dadurch eingebundenen Display Themes müssen sich In manchen Situationen kann es sinnvoll sein, dass ein Client nur einen Teil eines größeren JSON Topics schreiben (ggf. auch lesen?) kann. Ein Fall wären z.B. die Lade-Profile, wo vermutlich "Priorität" und "Standard nach Abstecken" für einen normalen Anwender nicht änderbar sein sollten, andere Daten wie "Lademodus" hingegen schon. Es müsste evaluiert werden, welche JSON Objekte im Hinblick auf ein Rechtemanagement aufzuteilen sind und dafür eine Lösung geschaffen werden. Primäres Ziel sollte es sein, dass nicht auch noch im Backend eine Benutzerverwaltung implementiert werden muss, sondern ausschließlich mit dem Rechtemanagement im Broker gearbeitet werden kann. Ansonsten müssten zwei Bereiche immer synchron gehalten werden, was früher oder später vermutlich zu Problemen führen wird. + +## 5. Besprechungen und Anpassungen + +### 5.1 Meeting 23.10.2025 + +#### 5.1.1 Notizen + +- vollumfängliche Umsetzung zeitlich problematisch (für Verkauf auch nicht erforderlich, einfache Umsetzung gefragt) +- 1\. step -> in jedem theme Anpassungen für optionale Nutzerverwaltung nötig (electron supporten) +- Security Plugin sichten +- Benutzer / ACL für Rechteinfo +- MQTT-basierte Sicherung (Backend erstmal außen vor lassen) +- **nur topic-basierte Rechte** im 1. step +- zuerst eine Login-Seite davor (self signed Zert.) +- Benutzerverwaltung komplett An/Aus schaltbar (Bestandsuser sollen so weiterarbeiten können, wie bisher) +- Button "Benutzer Wechsel / Logout" +- Displayseite mit Anmeldung am MQTT-Broker erforderlich (unterschiedlich bei primary / secondary) +- Benutzerpasswort zurücksetzen -> link an Lutz -> Github + +#### 5.1.2 Ausarbeitung + +1. Das Projekt wird in mehrere Schritte aufgeteilt, da die Umsetzung zeitkritisch ist und für den weiteren Verkauf nur eine teilweise umgesetzte Absicherung notwendig ist. Für WEGs ist eine Rechtevergabe für Ladepunkte und Fahrzeuge sowie Absicherung der anderen Einstellungen erforderlich, für den weiteren Vertrieb nach Österreich ein Kennwortschutz für die Einstellungen des Lastmanagements (inkl. I/O-Geräten und Aktionen). + +2. Im ersten Schritt sollen folgende Punkte umgesetzt werden: + +- Die Benutzerverwaltung soll komplett optional sein, damit Bestandsuser sich nicht umgewöhnen müssen. +- Rechtevergabe je Topic/Topic-Baum mittels des Dynamic Security Plugins für den Mosquitto Broker. +- Keine weiteren Einschränkungen im Backend +- Von den unter "4.1.1 Grundlegende Voraussetzungen" aufgeführten Punkten wird nur "4.1.1.1 Verschlüsselter Zugang" umgesetzt. +- Keine Anpassung nach Punkten 4.2, 4.3, 4.4 und 4.5. Dadurch müssen alle Themes und die Einstellungen so erweitert werden, dass ein An-/Abmelden möglich ist. Hier müssen die Display-Themes besonders betrachtet werden, da am Display keine interaktive Anmeldung möglich ist und zwischen dem Betrieb auf primary/secondary unterschieden werden muss. +- In den Einstellungen soll die ACL des angemeldeten Benutzers verwendet werden, um nur lesbare Einstellungen bzw. welche komplett ohne Zugriffsrechte anders darzustellen. +- Benutzer sollen bei einem vergessenen Passwort die Möglichkeit bekommen, sich über eine "Passwort vergessen" Funktion wieder anmelden zu können. + +#### 5.1.3 Einschätzung + +Die Benutzerverwaltung komplett abzuschalten halte ich nicht für sinnvoll. Hier sollte genau definiert werden, was dadurch erreicht werden soll. Wenn kein Rechtemanagement erforderlich ist, kann das durch einen einzelnen Benutzer mit sämtlichen Rechten erreicht werden. Das ist auch bei anderen im Heimbereich etablierten Produkten (z.B. FritzBox) seit Jahren Standard. + +Die Rechtevergabe ausschließlich über Topics zu regeln, wird in vielen Bereichen funktionieren, hat jedoch gerade bei größeren JSON-Objekten in den Topics seine Grenzen. Im einem der nächsten Schritte sollte die Rechtevergabe erweitert werden oder komplexe JSON-Objekte bei Bedarf aufgeteilt werden. + +Anpassungen im Backend sind für Teilbereiche nicht zu vermeiden. Bereits jetzt absehbar sind notwendige Änderungen bei der Aufbereitung der Diagrammdaten sowie Verarbeitung von "Commands". Bei den Diagrammen müssen Komponenten und Fahrzeuge, für welche keine Leseberechtigungen existieren, herausgefiltert werden. Sämtliche "Commands" werden an ein Topic gesendet, sodass eine Gültigkeitsprüfung nicht im Broker erfolgen kann. Diese beiden Punkte gehören meiner Meinung nach bereits in den ersten Schritt der Umsetzung. + +Den weggelassenen Punkt "4.1.1.3 Hostname und IP anpassbar" sehe ich gerade bei größeren Installationen (WEGs) kritisch. Zumindest der Hostname sollte individuell zu vergeben sein, um die Wallboxen besser identifizieren zu können und Namenskonflikte zu vermeiden. Der Aufwand dafür ist sehr gering, da bereits ein Skript unter "runs" vorhanden ist. Es muss lediglich im UI eingebunden werden. + +Weglassen der Punkte 4.2, 4.3, 4.4 und 4.5 schafft weitere notwendige Schnittstellen zwischen den einzelnen Projekten. Eine Weitergabe der Anmeldedaten über GET-Parameter einer URL ist nicht sinnvoll, da dadurch diese im Klartext einsehbar sind. Es ist nicht auszuschließen, dass ein Anwender sich mehrfach anmelden muss, wenn er z.B. von einem Theme zu den Einstellungen oder wieder zurück wechselt. + +Ob es anhand einer ausgelesenen ACL des Dynamic Security Plugins möglich ist, Eingabefelder entsprechend zu kennzeichnen, muss noch evaluiert werden. Die Rechte des angemeldeten Benutzers setzen sich aus mehreren Ebenen (Gruppe, Benutzer, Rolle) zusammen. Das kann sehr schnell komplex werden. + +Für die "Passwort vergessen" Funktion sind "Best Practices" einzuhalten, um keine unnötigen Angriffsflächen zu ermöglichen. In der aktuellen Umsetzung auf [GitHub openWB/forgot_password](https://github.com/openWB/forgot_password/tree/cbaa33cfb24fd5c4f55330c6f0010abf3962e48f) (Stand 24.10.2025, Commit cbaa33c vom 01.10.2025 19:29) werden die Zugangsdaten an unseren Server geschickt. Die Zugangsdaten dürfen niemals die openWB verlassen und ein Kennwort nicht im Klartext gespeichert werden. Die Funktionalität des Servers muss sich darauf beschränken, Daten von der openWB per Mail an den Benutzer zu senden. From a6eeea3fe0739f461b7f825eb0cc2fd4451f37f7 Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Mon, 27 Oct 2025 07:49:30 +0100 Subject: [PATCH 04/76] Kommentar Kevin - korrigiert --- .../Doku_Benutzerverwaltung.md | 67 ++++++++++++++++--- 1 file changed, 58 insertions(+), 9 deletions(-) diff --git a/web/Benutzerverwaltung/Doku_Benutzerverwaltung.md b/web/Benutzerverwaltung/Doku_Benutzerverwaltung.md index 8973363d59..00ede644ad 100644 --- a/web/Benutzerverwaltung/Doku_Benutzerverwaltung.md +++ b/web/Benutzerverwaltung/Doku_Benutzerverwaltung.md @@ -161,8 +161,8 @@ Der unter 2.2 aufgeführte "Theme-Wrapper" (Punkt 3.) muss im Zuge einer Benutze Oben wurde angesprochen, dass jedes Theme für die Links zu Status, Einstellungen etc. selbst verantwortlich ist. Es muss also in jedem Theme ein gewisser Anteil Code zwingend enthalten sein. Dabei stelle ich mir die Frage, ob das nicht einheitlich gelöst werden kann. -| ![Bereiche eines Themes - Koala]() | -|:--:| +| ![](Theme-Bereiche.png) | +|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:| | *Abbildung 1: Die farblich markierten Bereiche im Koala Theme zeigen, welche Funktionen einheitlich umgesetzt werden sollten (grün) und welche individuell vom Theme gestaltet werden (gelb).* | Am Beispiel des Koala Themes habe ich in Abbildung 1 zwei Bereiche eingefärbt. Grün hinterlegt ist die Funktionalität, welche in jedem Theme aktuell selbst umgesetzt werden muss. Der gelbe Bereich hingegen ist individuell vom jeweiligen Theme gestaltet. @@ -195,7 +195,7 @@ Der Display-Wrapper sowie die dadurch eingebundenen Display Themes müssen sich In manchen Situationen kann es sinnvoll sein, dass ein Client nur einen Teil eines größeren JSON Topics schreiben (ggf. auch lesen?) kann. Ein Fall wären z.B. die Lade-Profile, wo vermutlich "Priorität" und "Standard nach Abstecken" für einen normalen Anwender nicht änderbar sein sollten, andere Daten wie "Lademodus" hingegen schon. -Es müsste evaluiert werden, welche JSON Objekte im Hinblick auf ein Rechtemanagement aufzuteilen sind und dafür eine Lösung geschaffen werden. Primäres Ziel sollte es sein, dass nicht auch noch im Backend eine Benutzerverwaltung implementiert werden muss, sondern ausschließlich mit dem Rechtemanagement im Broker gearbeitet werden kann. Ansonsten müssten zwei Bereiche immer synchron gehalten werden, was früher oder später vermutlich zu Problemen führen wird. +Es müsste evaluiert werden, welche JSON Objekte im Hinblick auf ein Rechtemanagement aufzuteilen sind und dafür eine Lösung geschaffen werden. Primäres Ziel sollte es sein, dass nicht auch noch im Backend eine Benutzerverwaltung implementiert werden muss, sondern ausschließlich mit dem Rechtemanagement im Broker gearbeitet werden kann. Ansonsten müssten zwei Bereiche immer synchron gehalten werden, wa ## 5. Besprechungen und Anpassungen @@ -210,6 +210,9 @@ Es müsste evaluiert werden, welche JSON Objekte im Hinblick auf ein Rechtemanag - MQTT-basierte Sicherung (Backend erstmal außen vor lassen) - **nur topic-basierte Rechte** im 1. step - zuerst eine Login-Seite davor (self signed Zert.) + + **AnmkKW: Alternativ über Cloud über unser zertifikat.** + - Benutzerverwaltung komplett An/Aus schaltbar (Bestandsuser sollen so weiterarbeiten können, wie bisher) - Button "Benutzer Wechsel / Logout" - Displayseite mit Anmeldung am MQTT-Broker erforderlich (unterschiedlich bei primary / secondary) @@ -225,22 +228,68 @@ Es müsste evaluiert werden, welche JSON Objekte im Hinblick auf ein Rechtemanag - Rechtevergabe je Topic/Topic-Baum mittels des Dynamic Security Plugins für den Mosquitto Broker. - Keine weiteren Einschränkungen im Backend - Von den unter "4.1.1 Grundlegende Voraussetzungen" aufgeführten Punkten wird nur "4.1.1.1 Verschlüsselter Zugang" umgesetzt. -- Keine Anpassung nach Punkten 4.2, 4.3, 4.4 und 4.5. Dadurch müssen alle Themes und die Einstellungen so erweitert werden, dass ein An-/Abmelden möglich ist. Hier müssen die Display-Themes besonders betrachtet werden, da am Display keine interaktive Anmeldung möglich ist und zwischen dem Betrieb auf primary/secondary unterschieden werden muss. +- Keine Anpassung nach Punkten 4.2, 4.3, 4.4 und 4.5. Dadurch müssen alle Themes und die Einstellungen so erweitert werden, dass ein An-/Abmelden möglich ist. + + **AnmkKW: Sofern Auth aktiv ist Login/Abmelden Button. Login von der Hauptseite sollte bei Aufruf einstellungen übernommen werden ohne extra Eingabe.** + + Hier müssen die Display-Themes besonders betrachtet werden, da am Display keine interaktive Anmeldung möglich ist und zwischen dem Betrieb auf primary/secondary unterschieden werden muss. - In den Einstellungen soll die ACL des angemeldeten Benutzers verwendet werden, um nur lesbare Einstellungen bzw. welche komplett ohne Zugriffsrechte anders darzustellen. - Benutzer sollen bei einem vergessenen Passwort die Möglichkeit bekommen, sich über eine "Passwort vergessen" Funktion wieder anmelden zu können. #### 5.1.3 Einschätzung -Die Benutzerverwaltung komplett abzuschalten halte ich nicht für sinnvoll. Hier sollte genau definiert werden, was dadurch erreicht werden soll. Wenn kein Rechtemanagement erforderlich ist, kann das durch einen einzelnen Benutzer mit sämtlichen Rechten erreicht werden. Das ist auch bei anderen im Heimbereich etablierten Produkten (z.B. FritzBox) seit Jahren Standard. +Die Benutzerverwaltung komplett abzuschalten halte ich nicht für sinnvoll. Hier sollte genau definiert werden, was dadurch erreicht werden soll. + +**AnmkKW: Bei einem Update soll die openWB exakt identisch wie vorher funktioniert. Die Benutzerverwaltung ist ein optional aktivierbares Feature.** + +Wenn kein Rechtemanagement erforderlich ist, kann das durch einen einzelnen Benutzer mit sämtlichen Rechten erreicht werden. + +**AnmkKW: Hat aber ggf. einfluss auf vorhandens** + +Das ist auch bei anderen im Heimbereich etablierten Produkten (z.B. FritzBox) seit Jahren Standard. + +**AnmkKW: Aber da seit Ausilieferung. Bitte keine breaking changes.** + +Die Rechtevergabe ausschließlich über Topics zu regeln, wird in vielen Bereichen funktionieren, hat jedoch gerade bei größeren JSON-Objekten in den Topics seine Grenzen. + +**AnmkKW: Richtig. Erstmal aber akzeptabel** + +Im einem der nächsten Schritte sollte die Rechtevergabe erweitert werden oder komplexe JSON-Objekte bei Bedarf aufgeteilt werden. + +Anpassungen im Backend sind für Teilbereiche nicht zu vermeiden. Bereits jetzt absehbar sind notwendige Änderungen bei der Aufbereitung der Diagrammdaten sowie Verarbeitung von "Commands". -Die Rechtevergabe ausschließlich über Topics zu regeln, wird in vielen Bereichen funktionieren, hat jedoch gerade bei größeren JSON-Objekten in den Topics seine Grenzen. Im einem der nächsten Schritte sollte die Rechtevergabe erweitert werden oder komplexe JSON-Objekte bei Bedarf aufgeteilt werden. +**AnmkKW: Hatten wir erörtert, erstmal ist es "darf graph ansehen" Ja/nein. Welche Commands sind davon betroffen?** -Anpassungen im Backend sind für Teilbereiche nicht zu vermeiden. Bereits jetzt absehbar sind notwendige Änderungen bei der Aufbereitung der Diagrammdaten sowie Verarbeitung von "Commands". Bei den Diagrammen müssen Komponenten und Fahrzeuge, für welche keine Leseberechtigungen existieren, herausgefiltert werden. Sämtliche "Commands" werden an ein Topic gesendet, sodass eine Gültigkeitsprüfung nicht im Broker erfolgen kann. Diese beiden Punkte gehören meiner Meinung nach bereits in den ersten Schritt der Umsetzung. +Bei den Diagrammen müssen Komponenten und Fahrzeuge, für welche keine Leseberechtigungen existieren, herausgefiltert werden. -Den weggelassenen Punkt "4.1.1.3 Hostname und IP anpassbar" sehe ich gerade bei größeren Installationen (WEGs) kritisch. Zumindest der Hostname sollte individuell zu vergeben sein, um die Wallboxen besser identifizieren zu können und Namenskonflikte zu vermeiden. Der Aufwand dafür ist sehr gering, da bereits ein Skript unter "runs" vorhanden ist. Es muss lediglich im UI eingebunden werden. +**AnmkKW: Step2, erstmal nicht relevant** -Weglassen der Punkte 4.2, 4.3, 4.4 und 4.5 schafft weitere notwendige Schnittstellen zwischen den einzelnen Projekten. Eine Weitergabe der Anmeldedaten über GET-Parameter einer URL ist nicht sinnvoll, da dadurch diese im Klartext einsehbar sind. Es ist nicht auszuschließen, dass ein Anwender sich mehrfach anmelden muss, wenn er z.B. von einem Theme zu den Einstellungen oder wieder zurück wechselt. +Sämtliche "Commands" werden an ein Topic gesendet, sodass eine Gültigkeitsprüfung nicht im Broker erfolgen kann. Diese beiden Punkte gehören meiner Meinung nach bereits in den ersten Schritt der Umsetzung. + +**AnmkKW: Wir wollten einmal einmal Absicherung MQTT und Backend trennen. Somit eine Prüfung im Backend vorerst nicht durchführen** + +Den weggelassenen Punkt "4.1.1.3 Hostname und IP anpassbar" sehe ich gerade bei größeren Installationen (WEGs) kritisch. + +**AnmkKW: Das ist losgelöstes Thema zur Benutzerverwaltung** + + Zumindest der Hostname sollte individuell zu vergeben sein, um die Wallboxen besser identifizieren zu können und Namenskonflikte zu vermeiden. + +**AnmkKW: Bisher hat das gut funktioniert.** + +Der Aufwand dafür ist sehr gering, da bereits ein Skript unter "runs" vorhanden ist. Es muss lediglich im UI eingebunden werden. + +Weglassen der Punkte 4.2, 4.3, 4.4 und 4.5 schafft weitere notwendige Schnittstellen zwischen den einzelnen Projekten. Eine Weitergabe der Anmeldedaten über GET-Parameter einer URL ist nicht sinnvoll, da dadurch diese im Klartext einsehbar sind. + +**AnmkKW: Ein Cookie bietet sich hierfür an um das Problem zu lösen. Der User kann sich aussuchen ob es ohnehin nur kurzzeitig gültig ist, bis zum Abmelden oder auch 30 Tage Gültigkeit hat um ein stetiges authentifizieren zu vermeiden** + +Es ist nicht auszuschließen, dass ein Anwender sich mehrfach anmelden muss, wenn er z.B. von einem Theme zu den Einstellungen oder wieder zurück wechselt. + +**AnmkKW: Das muss ausgeschlossen werden -> Cookie** Ob es anhand einer ausgelesenen ACL des Dynamic Security Plugins möglich ist, Eingabefelder entsprechend zu kennzeichnen, muss noch evaluiert werden. Die Rechte des angemeldeten Benutzers setzen sich aus mehreren Ebenen (Gruppe, Benutzer, Rolle) zusammen. Das kann sehr schnell komplex werden. +**AnmkKW: Die Rollen beeinhalten schlussendlich Topics. Das DSP speichert dies in einem Json im Broker, ist also ggf. easy auszulesen.** + Für die "Passwort vergessen" Funktion sind "Best Practices" einzuhalten, um keine unnötigen Angriffsflächen zu ermöglichen. In der aktuellen Umsetzung auf [GitHub openWB/forgot_password](https://github.com/openWB/forgot_password/tree/cbaa33cfb24fd5c4f55330c6f0010abf3962e48f) (Stand 24.10.2025, Commit cbaa33c vom 01.10.2025 19:29) werden die Zugangsdaten an unseren Server geschickt. Die Zugangsdaten dürfen niemals die openWB verlassen und ein Kennwort nicht im Klartext gespeichert werden. Die Funktionalität des Servers muss sich darauf beschränken, Daten von der openWB per Mail an den Benutzer zu senden. + +**AnmkKW: Wird angepasst** From e46a01795d0e058f7fc1199852f0a52bab39905b Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Mon, 27 Oct 2025 13:46:14 +0100 Subject: [PATCH 05/76] dynsec Evaluierung 1 --- .../Doku_Benutzerverwaltung.md | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/web/Benutzerverwaltung/Doku_Benutzerverwaltung.md b/web/Benutzerverwaltung/Doku_Benutzerverwaltung.md index 00ede644ad..394fd4ec23 100644 --- a/web/Benutzerverwaltung/Doku_Benutzerverwaltung.md +++ b/web/Benutzerverwaltung/Doku_Benutzerverwaltung.md @@ -161,8 +161,8 @@ Der unter 2.2 aufgeführte "Theme-Wrapper" (Punkt 3.) muss im Zuge einer Benutze Oben wurde angesprochen, dass jedes Theme für die Links zu Status, Einstellungen etc. selbst verantwortlich ist. Es muss also in jedem Theme ein gewisser Anteil Code zwingend enthalten sein. Dabei stelle ich mir die Frage, ob das nicht einheitlich gelöst werden kann. -| ![](Theme-Bereiche.png) | -|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:| +| ![](Theme-Bereiche.png) | +| :---: | | *Abbildung 1: Die farblich markierten Bereiche im Koala Theme zeigen, welche Funktionen einheitlich umgesetzt werden sollten (grün) und welche individuell vom Theme gestaltet werden (gelb).* | Am Beispiel des Koala Themes habe ich in Abbildung 1 zwei Bereiche eingefärbt. Grün hinterlegt ist die Funktionalität, welche in jedem Theme aktuell selbst umgesetzt werden muss. Der gelbe Bereich hingegen ist individuell vom jeweiligen Theme gestaltet. @@ -197,11 +197,25 @@ In manchen Situationen kann es sinnvoll sein, dass ein Client nur einen Teil ein Es müsste evaluiert werden, welche JSON Objekte im Hinblick auf ein Rechtemanagement aufzuteilen sind und dafür eine Lösung geschaffen werden. Primäres Ziel sollte es sein, dass nicht auch noch im Backend eine Benutzerverwaltung implementiert werden muss, sondern ausschließlich mit dem Rechtemanagement im Broker gearbeitet werden kann. Ansonsten müssten zwei Bereiche immer synchron gehalten werden, wa -## 5. Besprechungen und Anpassungen +## 5. Evaluierung "Dynamic Security Plugin" für Mosquitto -### 5.1 Meeting 23.10.2025 +Das Plugin ist bereits mit den installierten Debian-Paketen auf dem Pi vorhanden wird in die `mosquitto.conf` eingebunden und aktiviert. Obwohl in der Dokumentation aufgeführt wird, dass die Parameter `plugin` und `plugin_opt_*` je Listener (`per_listener_settings = true`) definiert werden können, wird dies in der [Doku des Plugins](https://mosquitto.org/documentation/dynamic-security/#installation) nicht empfohlen. In einem Issue auf GitHub wurde das Problem mit einer älteren Version 2.0.13 diskutiert. Als Ergebnis der Diskussion erzeugt die mehrfache Definition des Plugins jetzt eine Warnmeldung, dass diese Konstellation nicht unterstützt wird und es zu Effekten wie doppelten Einträgen in der Konfigurationsdatei kommen kann. -#### 5.1.1 Notizen +Aktuell wird `per_listener_settings` in openWB verwendet, um für alle Ports außer `localhost:1884` (Brücke zum internen Broker) die jetzige ACL zu aktivieren. Die Brückendefinition müsste also um Anmeldedaten erweitert werden, um auf `per_listener_settings = false` umstellen zu können. + +In dem aktuell installierten Debian Bullseye ist die veraltete Version 2.0.11 (aus 2021!) enthalten, aktuell ist 2.0.22. Ein aktuelles Paket kann aus dem offiziellen [Repo](https://repo.mosquitto.org/debian) geladen werden. Das ist auch dringend zu empfehlen, weil in der Zwischenzeit reichlich Bugs behoben und besonders auch beim Dynamic Security Plugin Verbesserungen umgesetzt wurden. + +Auch in der aktuellen Version 2.0.22 unterstützt das Plugin nicht die Syntax, welche bei der aktuellen Date-ACL verwendet werden kann. Dort gibt es Platzhalter, die durch die Client-ID oder den Username ersetzt werden. openWB verwendet diese Syntax (Client-ID) für die Nachrichten, welche rechts in den Einstellungen bei der "Glocke" angezeigt werden. So kann jeder Client gezielt Nachrichten für seine Aktivitäten erhalten. Das Feature wurde für die kommende Version 2.1 bereits umgesetzt, jedoch gibt es noch keinen Termin für das Release. + +Das Plugin kann zwar Befehle über spezielle MQTT-Topics entgegennehmen, der Zugriff darf aber nicht für normale Clients aktiviert werden. Eine Freigabe hätte den vollen Zugang inkl. Benutzerverwaltung zur Folge. Die gesetzten Rechte werden **nicht** im Broker lesbar zur Verfügung gestellt. Eine Auswertung zur Laufzeit, wie es bei der Darstellung einzelner Eingabefelder angedacht war, erfordert also eine andere Datenquelle. Das gilt natürlich dann auch explizit für ein GUI zur Benutzerverwaltung. Es sind also zwei Datenbestände synchron zu halten, was ggf. mal zu Inkonsistenzen führen kann, wenn sich ein Bug einschleicht. Die festgelegten Zugriffsrechte des Plugins werden im JSON-Format gespeichert. Die Datei kann leicht in das Backup integriert werden. + +Bei einer ersten Testinstallation kam es mit der Version 2.0.22 zu Warnungen, dass die Zugriffsrechte der `mosquitto.acl` nicht korrekt gesetzt sind. Falls diese doch für den weiteren Betrieb benötigt wird, müssen die Berechtigungen auf `mosquitto:mosquitto` sowie `0600` angepasst werden. + +## Besprechungen und Anpassungen + +### 1 Meeting 23.10.2025 + +#### 1.1 Notizen - vollumfängliche Umsetzung zeitlich problematisch (für Verkauf auch nicht erforderlich, einfache Umsetzung gefragt) - 1\. step -> in jedem theme Anpassungen für optionale Nutzerverwaltung nötig (electron supporten) From 7b2f22af592e46a144b7643955b6d31ec94ee54b Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Mon, 3 Nov 2025 11:18:31 +0100 Subject: [PATCH 06/76] restrict access to mosquitto and apache --- data/config/apache/000-default.conf | 12 ++++++--- data/config/apache/apache-openwb-ssl.conf | 13 ++++++--- data/config/apache/apache-redirect-ssl.conf | 29 +++++++++++++++++++++ data/config/mosquitto/mosquitto.conf | 9 ++++++- data/config/mosquitto/openwb.conf | 24 +---------------- data/config/mosquitto/openwb_insecure.conf | 13 +++++++++ openwb-install.sh | 1 + packages/helpermodules/update_config.py | 2 ++ runs/atreboot.sh | 18 +++++++++++++ runs/setup_apache2.sh | 22 +++++++++++----- 10 files changed, 105 insertions(+), 38 deletions(-) create mode 100644 data/config/apache/apache-redirect-ssl.conf create mode 100644 data/config/mosquitto/openwb_insecure.conf diff --git a/data/config/apache/000-default.conf b/data/config/apache/000-default.conf index 00def235e1..1e70d47e25 100644 --- a/data/config/apache/000-default.conf +++ b/data/config/apache/000-default.conf @@ -1,4 +1,4 @@ -# openwb-version:5 +# openwb-version:6 # The ServerName directive sets the request scheme, hostname and port that # the server uses to identify itself. This is used when creating @@ -37,9 +37,13 @@ # after it has been globally disabled with "a2disconf". #Include conf-available/serve-cgi-bin.conf - ProxyPass "/ws" "ws://localhost:9001" - # ToDo: remove the next line when main page is using vue.js - ProxyPass "/mqtt" "ws://localhost:9001" + # Proxy WebSocket and MQTT connections to Mosquitto + SSLProxyEngine On + SSLProxyVerify none + SSLProxyCheckPeerCN Off + SSLProxyCheckPeerName Off + # ToDo: remove /mqtt target once all clients use /ws + ProxyPassMatch "^/(ws|mqtt)(/|$)" "wss://127.0.0.1:9002/" # vim: syntax=apache ts=4 sw=4 sts=4 sr noet diff --git a/data/config/apache/apache-openwb-ssl.conf b/data/config/apache/apache-openwb-ssl.conf index 9603094810..2ade43286a 100644 --- a/data/config/apache/apache-openwb-ssl.conf +++ b/data/config/apache/apache-openwb-ssl.conf @@ -1,4 +1,4 @@ -# openwb-version:6 +# openwb-version:7 ServerAdmin webmaster@localhost @@ -139,9 +139,14 @@ # nokeepalive ssl-unclean-shutdown \ # downgrade-1.0 force-response-1.0 - ProxyPass "/ws" "ws://localhost:9001" - # ToDo: remove the next line when main page is using vue.js - ProxyPass "/mqtt" "ws://localhost:9001" + # Proxy WebSocket and MQTT connections to Mosquitto + SSLProxyEngine On + SSLProxyVerify none + SSLProxyCheckPeerCN Off + SSLProxyCheckPeerName Off + # ToDo: remove /mqtt target once all clients use /ws + ProxyPassMatch "^/(ws|mqtt)(/|$)" "wss://127.0.0.1:9002/" + diff --git a/data/config/apache/apache-redirect-ssl.conf b/data/config/apache/apache-redirect-ssl.conf new file mode 100644 index 0000000000..8ee4d9c539 --- /dev/null +++ b/data/config/apache/apache-redirect-ssl.conf @@ -0,0 +1,29 @@ +# openwb-version:1 + + # The ServerName directive sets the request scheme, hostname and port that + # the server uses to identify itself. This is used when creating + # redirection URLs. In the context of virtual hosts, the ServerName + # specifies what hostname must appear in the request's Host: header to + # match this virtual host. For the default virtual host (this file) this + # value is not decisive as it is used as a last resort host regardless. + # However, you must set it for any further virtual host explicitly. + #ServerName www.example.com + + ServerAdmin webmaster@localhost + DocumentRoot /var/www/html + # Available loglevels: trace8, ..., trace1, debug, info, notice, warn, + # error, crit, alert, emerg. + # It is also possible to configure the loglevel for particular + # modules, e.g. + #LogLevel info ssl:warn + + ErrorLog ${APACHE_LOG_DIR}/error.log + #CustomLog ${APACHE_LOG_DIR}/access.log combined + + # redirect all HTTP traffic to HTTPS + RewriteEngine On + RewriteCond %{HTTPS} off + RewriteRule ^/?(.*)$ https://%{HTTP_HOST}/$1 [R=301,L] + + +# vim: syntax=apache ts=4 sw=4 sts=4 sr noet diff --git a/data/config/mosquitto/mosquitto.conf b/data/config/mosquitto/mosquitto.conf index ff333ccbf8..bc9b0041a6 100644 --- a/data/config/mosquitto/mosquitto.conf +++ b/data/config/mosquitto/mosquitto.conf @@ -1,4 +1,4 @@ -# openwb-version:2 +# openwb-version:3 persistence true persistence_location /var/lib/mosquitto/ log_type error @@ -8,4 +8,11 @@ log_dest file /var/log/mosquitto/mosquitto.log # only enable on bullseye and newer log_timestamp_format %Y-%m-%dT%H:%M:%S +# required to restrict access per listener +per_listener_settings true + +# prevent too many inactive connections from buggy clients +# closes inactive connections after 4 hours +persistent_client_expiration 4h + include_dir /etc/mosquitto/conf.d diff --git a/data/config/mosquitto/openwb.conf b/data/config/mosquitto/openwb.conf index ecff1f6de4..8f3402f20a 100644 --- a/data/config/mosquitto/openwb.conf +++ b/data/config/mosquitto/openwb.conf @@ -1,19 +1,4 @@ -# openwb-version:3 - -# required to restrict access per listener -per_listener_settings true - -# prevent too many inactive connections from buggy clients -# closes inactive connections after 4 hours -persistent_client_expiration 4h - -# this websocket is used by local apache -# todo: restrict access: -# listener 9001 localhost -listener 9001 -protocol websockets -allow_anonymous true -acl_file /etc/mosquitto/mosquitto.acl +# openwb-version:4 # public secure websocket listener listener 9002 @@ -28,13 +13,6 @@ listener 1884 localhost protocol mqtt allow_anonymous true -# public unsecure mqtt listener -# todo: remove unsecure listeners -listener 1883 -protocol mqtt -allow_anonymous true -acl_file /etc/mosquitto/mosquitto.acl - # public secure mqtt listener listener 8883 protocol mqtt diff --git a/data/config/mosquitto/openwb_insecure.conf b/data/config/mosquitto/openwb_insecure.conf new file mode 100644 index 0000000000..ccb6ce37c7 --- /dev/null +++ b/data/config/mosquitto/openwb_insecure.conf @@ -0,0 +1,13 @@ +# openwb-version:1 + +# public unsecure mqtt listener +listener 1883 +protocol mqtt +allow_anonymous true +acl_file /etc/mosquitto/mosquitto.acl + +# public unsecure websocket listener +listener 9001 +protocol websockets +allow_anonymous true +acl_file /etc/mosquitto/mosquitto.acl diff --git a/openwb-install.sh b/openwb-install.sh index 3ed8cc4f0a..6af394a1fe 100755 --- a/openwb-install.sh +++ b/openwb-install.sh @@ -63,6 +63,7 @@ systemctl stop mosquitto sleep 2 cp -a "${OPENWBBASEDIR}/data/config/mosquitto/mosquitto.conf" /etc/mosquitto/mosquitto.conf cp "${OPENWBBASEDIR}/data/config/mosquitto/openwb.conf" /etc/mosquitto/conf.d/openwb.conf +cp "${OPENWBBASEDIR}/data/config/mosquitto/openwb_insecure.conf" /etc/mosquitto/conf.d/openwb_insecure.conf.disabled cp "${OPENWBBASEDIR}/data/config/mosquitto/mosquitto.acl" /etc/mosquitto/mosquitto.acl sudo cp /etc/ssl/certs/ssl-cert-snakeoil.pem /etc/mosquitto/certs/openwb.pem sudo cp /etc/ssl/private/ssl-cert-snakeoil.key /etc/mosquitto/certs/openwb.key diff --git a/packages/helpermodules/update_config.py b/packages/helpermodules/update_config.py index 15530c627d..a319a6650f 100644 --- a/packages/helpermodules/update_config.py +++ b/packages/helpermodules/update_config.py @@ -200,6 +200,7 @@ class UpdateConfig: "^openWB/counter/[0-9]+/config/max_currents$", "^openWB/counter/[0-9]+/config/max_total_power$", + "^openWB/general/allow_unencrypted_access$", "^openWB/general/extern$", "^openWB/general/extern_display_mode$", "^openWB/general/charge_log_data_config$", @@ -532,6 +533,7 @@ class UpdateConfig: ("openWB/vehicle/template/ev_template/0", asdict(EvTemplateData(name="Standard-Fahrzeug-Profil", min_current=10))), ("openWB/vehicle/template/charge_template/0", get_charge_template_default()), + ("openWB/general/allow_unencrypted_access", False), ("openWB/general/charge_log_data_config", get_default_charge_log_columns()), ("openWB/general/chargemode_config/pv_charging/bat_mode", BatConsiderationMode.EV_MODE.value), ("openWB/general/chargemode_config/pv_charging/bat_power_discharge", 1000), diff --git a/runs/atreboot.sh b/runs/atreboot.sh index 3485ec0c3d..0ac937dc42 100755 --- a/runs/atreboot.sh +++ b/runs/atreboot.sh @@ -351,6 +351,24 @@ chmod 666 "$LOGFILE" sudo cp "${OPENWBBASEDIR}/data/config/mosquitto/openwb.conf" "/etc/mosquitto/conf.d/openwb.conf" restartService=1 fi + allowUnencryptedAccess=$(mosquitto_sub -t "openWB/general/allow_unencrypted_access" -p 1886 -C 1 -W 1 --quiet) + if [[ $allowUnencryptedAccess == "true" ]]; then + if versionMatch "${OPENWBBASEDIR}/data/config/mosquitto/openwb_insecure.conf" "/etc/mosquitto/conf.d/openwb_insecure.conf"; then + echo "mosquitto openwb_insecure.conf already up to date" + else + echo "updating mosquitto openwb_insecure.conf" + sudo cp "${OPENWBBASEDIR}/data/config/mosquitto/openwb_insecure.conf" "/etc/mosquitto/conf.d/openwb_insecure.conf" + restartService=1 + fi + else + if [ -f "/etc/mosquitto/conf.d/openwb_insecure.conf" ]; then + echo "removing mosquitto openwb_insecure.conf" + sudo rm "/etc/mosquitto/conf.d/openwb_insecure.conf" + restartService=1 + else + echo "mosquitto openwb_insecure.conf not present, no action needed" + fi + fi if versionMatch "${OPENWBBASEDIR}/data/config/mosquitto/mosquitto.acl" "/etc/mosquitto/mosquitto.acl"; then echo "mosquitto acl already up to date" else diff --git a/runs/setup_apache2.sh b/runs/setup_apache2.sh index 6456fa7bde..a31e21ab70 100755 --- a/runs/setup_apache2.sh +++ b/runs/setup_apache2.sh @@ -72,12 +72,16 @@ disableSite() { # check apache modules echo "checking required apache modules..." enableModule headers +enableModule rewrite enableModule ssl +enableModule proxy_http enableModule proxy_wstunnel # default site (http and https) echo "apache default site..." updateFile "${OPENWBBASEDIR}/data/config/apache/000-default.conf" "/etc/apache2/sites-available/000-default.conf" +echo "apache redirect ssl site..." +updateFile "${OPENWBBASEDIR}/data/config/apache/apache-redirect-ssl.conf" "/etc/apache2/sites-available/apache-redirect-ssl.conf" echo "apache default ssl site..." updateFile "${OPENWBBASEDIR}/data/config/apache/apache-openwb-ssl.conf" "/etc/apache2/sites-available/apache-openwb-ssl.conf" # http api site (https only) @@ -91,6 +95,18 @@ updateFile "${OPENWBBASEDIR}/data/config/apache/apache-proplus.conf" "/etc/apach disableSite default-ssl # enable openwb ssl site enableSite apache-openwb-ssl +# check if https only access is configured +allowUnencryptedAccess=$(mosquitto_sub -t "openWB/general/allow_unencrypted_access" -p 1886 -C 1 -W 1 --quiet) +if [[ $allowUnencryptedAccess == "true" ]]; then + echo "https only is disabled" + disableSite apache-redirect-ssl + enableSite 000-default +else + echo "https only is enabled" + disableSite 000-default + enableSite apache-redirect-ssl +fi + # enable http api ssl site if configured httpApiEnabled=$(mosquitto_sub -t "openWB/general/http_api" -p 1886 -C 1 -W 1 --quiet) if [[ $httpApiEnabled == "true" ]]; then @@ -106,16 +122,10 @@ echo "Pro+ setup..." if lsusb | grep -q 'RTL8153'; then echo "second network for pro plus detected" # enable pro+ specific configurations - enableModule proxy_http - # enableModule proxy_fcgi - # enableModule proxy_ajp enableSite apache-proplus else echo "no second network for pro plus detected" # disable all pro+ specific configurations - disableModule proxy_http - # disableModule proxy_fcgi - # disableModule proxy_ajp disableSite apache-proplus fi From 1f24f9b14775d976c04a5fec239c7ac6042cb92e Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Mon, 3 Nov 2025 13:06:43 +0100 Subject: [PATCH 07/76] move mosquitto setup to own file --- runs/atreboot.sh | 115 +------------------------------- runs/setup_apache2.sh | 6 +- runs/setup_mosquitto.sh | 141 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 145 insertions(+), 117 deletions(-) create mode 100755 runs/setup_mosquitto.sh diff --git a/runs/atreboot.sh b/runs/atreboot.sh index 0ac937dc42..d9ae9bd7fb 100755 --- a/runs/atreboot.sh +++ b/runs/atreboot.sh @@ -21,30 +21,6 @@ chmod 666 "$LOGFILE" fi } - waitForServiceStop() { - # this function waits for a service to stop and kills the process if it takes too long - # this is necessary at least for mosquitto, as the service is stopped, but the process is still running - service=$1 - pattern=$2 - timeout=$3 - - counter=0 - sudo systemctl stop "$service" - while pgrep --full "$pattern" >/dev/null && ((counter < timeout)); do - echo "process '$pattern' still running after ${counter}s, waiting..." - sleep 1 - ((counter++)) - done - if ((counter >= timeout)); then - echo "process '$pattern' still running after ${timeout}s, killing process" - sudo pkill --full "$pattern" --signal 9 - sleep 2 - # if the process was killed, the service is in "active (exited)" state - # so we need to trigger a stop here to be able to start it again - sudo systemctl stop "$service" - fi - } - if ! id -u openwb >/dev/null 2>&1; then echo "user 'openwb' missing" echo "starting upgrade script..." @@ -335,96 +311,7 @@ chmod 666 "$LOGFILE" "${OPENWBBASEDIR}/runs/setup_apache2.sh" # check for mosquitto configuration - echo "check mosquitto installation..." - restartService=0 - if versionMatch "${OPENWBBASEDIR}/data/config/mosquitto/mosquitto.conf" "/etc/mosquitto/mosquitto.conf"; then - echo "mosquitto.conf already up to date" - else - echo "updating mosquitto.conf" - sudo cp "${OPENWBBASEDIR}/data/config/mosquitto/mosquitto.conf" "/etc/mosquitto/mosquitto.conf" - restartService=1 - fi - if versionMatch "${OPENWBBASEDIR}/data/config/mosquitto/openwb.conf" "/etc/mosquitto/conf.d/openwb.conf"; then - echo "mosquitto openwb.conf already up to date" - else - echo "updating mosquitto openwb.conf" - sudo cp "${OPENWBBASEDIR}/data/config/mosquitto/openwb.conf" "/etc/mosquitto/conf.d/openwb.conf" - restartService=1 - fi - allowUnencryptedAccess=$(mosquitto_sub -t "openWB/general/allow_unencrypted_access" -p 1886 -C 1 -W 1 --quiet) - if [[ $allowUnencryptedAccess == "true" ]]; then - if versionMatch "${OPENWBBASEDIR}/data/config/mosquitto/openwb_insecure.conf" "/etc/mosquitto/conf.d/openwb_insecure.conf"; then - echo "mosquitto openwb_insecure.conf already up to date" - else - echo "updating mosquitto openwb_insecure.conf" - sudo cp "${OPENWBBASEDIR}/data/config/mosquitto/openwb_insecure.conf" "/etc/mosquitto/conf.d/openwb_insecure.conf" - restartService=1 - fi - else - if [ -f "/etc/mosquitto/conf.d/openwb_insecure.conf" ]; then - echo "removing mosquitto openwb_insecure.conf" - sudo rm "/etc/mosquitto/conf.d/openwb_insecure.conf" - restartService=1 - else - echo "mosquitto openwb_insecure.conf not present, no action needed" - fi - fi - if versionMatch "${OPENWBBASEDIR}/data/config/mosquitto/mosquitto.acl" "/etc/mosquitto/mosquitto.acl"; then - echo "mosquitto acl already up to date" - else - echo "updating mosquitto acl" - sudo cp "${OPENWBBASEDIR}/data/config/mosquitto/mosquitto.acl" "/etc/mosquitto/mosquitto.acl" - restartService=1 - fi - if [[ ! -f "/etc/mosquitto/certs/openwb.key" ]]; then - echo -n "copy ssl certs..." - sudo cp "/etc/ssl/certs/ssl-cert-snakeoil.pem" "/etc/mosquitto/certs/openwb.pem" - sudo cp "/etc/ssl/private/ssl-cert-snakeoil.key" "/etc/mosquitto/certs/openwb.key" - sudo chgrp mosquitto "/etc/mosquitto/certs/openwb.key" - restartService=1 - echo "done" - fi - if ((restartService == 1)); then - echo -n "restarting mosquitto service..." - waitForServiceStop "mosquitto" "mosquitto.conf" 10 - sudo systemctl start mosquitto - echo "done" - fi - - #check for mosquitto_local instance - # restartService=0 # if we restart mosquitto, we need to restart mosquitto_local as well - if versionMatch "${OPENWBBASEDIR}/data/config/mosquitto/mosquitto_local_init" "/etc/init.d/mosquitto_local"; then - echo "mosquitto_local service definition already up to date" - else - echo "updating mosquitto_local service definition" - sudo cp "${OPENWBBASEDIR}/data/config/mosquitto/mosquitto_local_init" /etc/init.d/mosquitto_local - sudo chown root:root /etc/init.d/mosquitto_local - sudo chmod 755 /etc/init.d/mosquitto_local - sudo systemctl daemon-reload - sudo systemctl enable mosquitto_local - restartService=1 - fi - if versionMatch "${OPENWBBASEDIR}/data/config/mosquitto/mosquitto_local.conf" "/etc/mosquitto/mosquitto_local.conf"; then - echo "mosquitto_local.conf already up to date" - else - echo "updating mosquitto_local.conf" - sudo cp -a "${OPENWBBASEDIR}/data/config/mosquitto/mosquitto_local.conf" "/etc/mosquitto/mosquitto_local.conf" - restartService=1 - fi - if versionMatch "${OPENWBBASEDIR}/data/config/mosquitto/openwb_local.conf" "/etc/mosquitto/conf_local.d/openwb_local.conf"; then - echo "mosquitto openwb_local.conf already up to date" - else - echo "updating mosquitto openwb_local.conf" - sudo cp -a "${OPENWBBASEDIR}/data/config/mosquitto/openwb_local.conf" "/etc/mosquitto/conf_local.d/" - restartService=1 - fi - if ((restartService == 1)); then - echo -n "restarting mosquitto_local service..." - waitForServiceStop "mosquitto_local" "mosquitto_local.conf" 10 - sudo systemctl start mosquitto_local - echo "done" - fi - echo "mosquitto done" + "${OPENWBBASEDIR}/runs/setup_mosquitto.sh" 1 # check for home configuration if [[ ! -f "/home/openwb/configuration.json" ]]; then diff --git a/runs/setup_apache2.sh b/runs/setup_apache2.sh index a31e21ab70..961eacb6f2 100755 --- a/runs/setup_apache2.sh +++ b/runs/setup_apache2.sh @@ -95,14 +95,14 @@ updateFile "${OPENWBBASEDIR}/data/config/apache/apache-proplus.conf" "/etc/apach disableSite default-ssl # enable openwb ssl site enableSite apache-openwb-ssl -# check if https only access is configured +# check if unencrypted access is configured allowUnencryptedAccess=$(mosquitto_sub -t "openWB/general/allow_unencrypted_access" -p 1886 -C 1 -W 1 --quiet) if [[ $allowUnencryptedAccess == "true" ]]; then - echo "https only is disabled" + echo "WARNING: unencrypted access is enabled!" disableSite apache-redirect-ssl enableSite 000-default else - echo "https only is enabled" + echo "unencrypted access is disabled" disableSite 000-default enableSite apache-redirect-ssl fi diff --git a/runs/setup_mosquitto.sh b/runs/setup_mosquitto.sh new file mode 100755 index 0000000000..830fae155c --- /dev/null +++ b/runs/setup_mosquitto.sh @@ -0,0 +1,141 @@ +#!/bin/bash +OPENWBBASEDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) +automaticServiceRestart=${1:-0} + +versionMatch() { + file=$1 + target=$2 + currentVersion=$(grep -o "openwb-version:[0-9]\+" "$file" | grep -o "[0-9]\+$") + installedVersion=$(sudo grep -o "openwb-version:[0-9]\+" "$target" | grep -o "[0-9]\+$") + if ((currentVersion == installedVersion)); then + return 0 + else + return 1 + fi +} + +waitForServiceStop() { + # this function waits for a service to stop and kills the process if it takes too long + # this is necessary at least for mosquitto, as the service is stopped, but the process is still running + service=$1 + pattern=$2 + timeout=$3 + + counter=0 + sudo systemctl stop "$service" + while pgrep --full "$pattern" >/dev/null && ((counter < timeout)); do + echo "process '$pattern' still running after ${counter}s, waiting..." + sleep 1 + ((counter++)) + done + if ((counter >= timeout)); then + echo "process '$pattern' still running after ${timeout}s, killing process" + sudo pkill --full "$pattern" --signal 9 + sleep 2 + # if the process was killed, the service is in "active (exited)" state + # so we need to trigger a stop here to be able to start it again + sudo systemctl stop "$service" + fi +} + +# check for mosquitto configuration +echo "check mosquitto installation..." +restartService=0 + +echo "mosquitto main configuration..." +if versionMatch "${OPENWBBASEDIR}/data/config/mosquitto/mosquitto.conf" "/etc/mosquitto/mosquitto.conf"; then + echo "mosquitto.conf already up to date" +else + echo "updating mosquitto.conf" + sudo cp "${OPENWBBASEDIR}/data/config/mosquitto/mosquitto.conf" "/etc/mosquitto/mosquitto.conf" + restartService=1 +fi + +echo "mosquitto openwb configuration..." +if versionMatch "${OPENWBBASEDIR}/data/config/mosquitto/openwb.conf" "/etc/mosquitto/conf.d/openwb.conf"; then + echo "mosquitto openwb.conf already up to date" +else + echo "updating mosquitto openwb.conf" + sudo cp "${OPENWBBASEDIR}/data/config/mosquitto/openwb.conf" "/etc/mosquitto/conf.d/openwb.conf" + restartService=1 +fi + +allowUnencryptedAccess=$(mosquitto_sub -t "openWB/general/allow_unencrypted_access" -p 1886 -C 1 -W 1 --quiet) +if [[ $allowUnencryptedAccess == "true" ]]; then + if versionMatch "${OPENWBBASEDIR}/data/config/mosquitto/openwb_insecure.conf" "/etc/mosquitto/conf.d/openwb_insecure.conf"; then + echo "mosquitto openwb_insecure.conf already up to date" + else + echo "updating mosquitto openwb_insecure.conf" + sudo cp "${OPENWBBASEDIR}/data/config/mosquitto/openwb_insecure.conf" "/etc/mosquitto/conf.d/openwb_insecure.conf" + restartService=1 + fi +else + if [ -f "/etc/mosquitto/conf.d/openwb_insecure.conf" ]; then + echo "removing mosquitto openwb_insecure.conf" + sudo rm "/etc/mosquitto/conf.d/openwb_insecure.conf" + restartService=1 + else + echo "mosquitto openwb_insecure.conf not present, no action needed" + fi +fi + +echo "mosquitto acl configuration..." +if versionMatch "${OPENWBBASEDIR}/data/config/mosquitto/mosquitto.acl" "/etc/mosquitto/mosquitto.acl"; then + echo "mosquitto acl already up to date" +else + echo "updating mosquitto acl" + sudo cp "${OPENWBBASEDIR}/data/config/mosquitto/mosquitto.acl" "/etc/mosquitto/mosquitto.acl" + restartService=1 +fi + +echo "mosquitto certificates..." +if [[ ! -f "/etc/mosquitto/certs/openwb.key" ]]; then + echo -n "copy ssl certs..." + sudo cp "/etc/ssl/certs/ssl-cert-snakeoil.pem" "/etc/mosquitto/certs/openwb.pem" + sudo cp "/etc/ssl/private/ssl-cert-snakeoil.key" "/etc/mosquitto/certs/openwb.key" + sudo chgrp mosquitto "/etc/mosquitto/certs/openwb.key" + restartService=1 + echo "done" +fi +if ((restartService == 1 && automaticServiceRestart == 1)); then + echo -n "restarting mosquitto service..." + waitForServiceStop "mosquitto" "mosquitto.conf" 10 + sudo systemctl start mosquitto + echo "done" +fi + +#check for mosquitto_local instance +# restartService=0 # if we restart mosquitto, we need to restart mosquitto_local as well +echo "mosquitto_local instance..." +if versionMatch "${OPENWBBASEDIR}/data/config/mosquitto/mosquitto_local_init" "/etc/init.d/mosquitto_local"; then + echo "mosquitto_local service definition already up to date" +else + echo "updating mosquitto_local service definition" + sudo cp "${OPENWBBASEDIR}/data/config/mosquitto/mosquitto_local_init" /etc/init.d/mosquitto_local + sudo chown root:root /etc/init.d/mosquitto_local + sudo chmod 755 /etc/init.d/mosquitto_local + sudo systemctl daemon-reload + sudo systemctl enable mosquitto_local + restartService=1 +fi +if versionMatch "${OPENWBBASEDIR}/data/config/mosquitto/mosquitto_local.conf" "/etc/mosquitto/mosquitto_local.conf"; then + echo "mosquitto_local.conf already up to date" +else + echo "updating mosquitto_local.conf" + sudo cp -a "${OPENWBBASEDIR}/data/config/mosquitto/mosquitto_local.conf" "/etc/mosquitto/mosquitto_local.conf" + restartService=1 +fi +if versionMatch "${OPENWBBASEDIR}/data/config/mosquitto/openwb_local.conf" "/etc/mosquitto/conf_local.d/openwb_local.conf"; then + echo "mosquitto openwb_local.conf already up to date" +else + echo "updating mosquitto openwb_local.conf" + sudo cp -a "${OPENWBBASEDIR}/data/config/mosquitto/openwb_local.conf" "/etc/mosquitto/conf_local.d/" + restartService=1 +fi +if ((restartService == 1 && automaticServiceRestart == 1)); then + echo -n "restarting mosquitto_local service..." + waitForServiceStop "mosquitto_local" "mosquitto_local.conf" 10 + sudo systemctl start mosquitto_local + echo "done" +fi +echo "mosquitto done" From 8b7cf00a87d83280e6cfa87616fb5016900edce3 Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Mon, 3 Nov 2025 13:07:55 +0100 Subject: [PATCH 08/76] implement dis-/enabling unencrypted access --- packages/control/general.py | 2 ++ packages/helpermodules/setdata.py | 3 ++- packages/helpermodules/subdata.py | 28 ++++++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/packages/control/general.py b/packages/control/general.py index 388e83514a..8bbed5aac3 100644 --- a/packages/control/general.py +++ b/packages/control/general.py @@ -99,6 +99,8 @@ class GeneralData: default=None, metadata={"topic": "grid_protection_timestamp"}) http_api: bool = field( default=False, metadata={"topic": "http_api"}) + allow_unencrypted_access: bool = field( + default=False, metadata={"topic": "allow_unencrypted_access"}) mqtt_bridge: bool = False temporary_charge_templates_active: bool = False prices: Prices = field(default_factory=prices_factory) diff --git a/packages/helpermodules/setdata.py b/packages/helpermodules/setdata.py index 1454527dba..2f75a77c2e 100644 --- a/packages/helpermodules/setdata.py +++ b/packages/helpermodules/setdata.py @@ -725,7 +725,8 @@ def process_general_topic(self, msg: mqtt.MQTTMessage): self._validate_value(msg, str) elif ("openWB/set/general/http_api" in msg.topic or "openWB/set/general/modbus_control" in msg.topic or - "openWB/set/general/extern" in msg.topic): + "openWB/set/general/extern" in msg.topic or + "openWB/set/general/allow_unencrypted_access" in msg.topic): self._validate_value(msg, bool) elif "openWB/set/general/control_interval" in msg.topic: self._validate_value(msg, int, [(10, 10), (20, 20), (60, 60)]) diff --git a/packages/helpermodules/subdata.py b/packages/helpermodules/subdata.py index b5b2856e0c..9f8c66a9b7 100644 --- a/packages/helpermodules/subdata.py +++ b/packages/helpermodules/subdata.py @@ -621,6 +621,34 @@ def process_general_topic(self, var: general.General, msg: mqtt.MQTTMessage): MessageType.SUCCESS ) self.set_json_payload_class(var.data, msg) + elif "openWB/general/allow_unencrypted_access" == msg.topic: + allow_unencrypted_access = decode_payload(msg.payload) + log.warning(f"Topic: 'allow_unencrypted_access' Payload: {allow_unencrypted_access}") + log.warning(f"Aktuelle Einstellung: {self.general_data.data.allow_unencrypted_access}") + log.warning("Event subdata_initialized: " + f"{self.event_subdata_initialized.is_set()}") + if ( + self.event_subdata_initialized.is_set() and + self.general_data.data.allow_unencrypted_access != allow_unencrypted_access + ): + log.warning("Änderung der Einstellung 'allow_unencrypted_access' erkannt.") + run_command([ + str(Path(__file__).resolve().parents[2] / "runs" / "setup_apache2.sh") + ], process_exception=True) + log.warning("Apache2-Konfiguration wurde angepasst.") + run_command([ + str(Path(__file__).resolve().parents[2] / "runs" / "setup_mosquitto.sh"), + "0" # kein Neustart im laufenden Betrieb! + ], process_exception=True) + log.warning("Mosquitto-Konfiguration wurde angepasst.") + pub_system_message( + msg.payload, + f"Unsichere Verbindungen wurden {'' if allow_unencrypted_access else 'de'}aktiviert.
" + "Bitte die openWB " + "neu starten, damit die Änderungen wirksam werden.", + MessageType.WARNING + ) + self.set_json_payload_class(var.data, msg) else: self.set_json_payload_class(var.data, msg) except Exception: From a07419ddfa36f4636be801b55a7065a2585b9af6 Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Mon, 10 Nov 2025 10:19:30 +0100 Subject: [PATCH 09/76] migrate simpleAPI --- data/config/simpleAPI_mqtt_config.json | 7 ++++--- simpleAPI/config/config.php | 5 +++-- simpleAPI/simpleAPI_mqtt.py | 3 +++ simpleAPI/src/MqttClient.php | 11 +++++++++-- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/data/config/simpleAPI_mqtt_config.json b/data/config/simpleAPI_mqtt_config.json index 9a7de748ec..d1b06a2844 100644 --- a/data/config/simpleAPI_mqtt_config.json +++ b/data/config/simpleAPI_mqtt_config.json @@ -1,11 +1,12 @@ { "host": "localhost", - "port": 1883, + "port": 8883, "username": null, "password": null, - "use_tls": false, + "use_tls": true, + "validate_cert": false, "qos": 0, "retain": true, "reconnect_delay": 10, "log_level": "INFO" -} \ No newline at end of file +} diff --git a/simpleAPI/config/config.php b/simpleAPI/config/config.php index 0dddb3a5f6..0a0ee92c58 100644 --- a/simpleAPI/config/config.php +++ b/simpleAPI/config/config.php @@ -4,7 +4,8 @@ // MQTT Broker Konfiguration 'mqtt' => [ 'server' => 'localhost', - 'port' => 1883, + 'port' => 8883, + 'validate_cert' => false, 'username' => '', 'password' => '', 'clientid' => 'SimpleAPI_' . uniqid() @@ -35,4 +36,4 @@ // Debug-Modus 'debug' => false -]; \ No newline at end of file +]; diff --git a/simpleAPI/simpleAPI_mqtt.py b/simpleAPI/simpleAPI_mqtt.py index 9935362733..2882fcfd9e 100755 --- a/simpleAPI/simpleAPI_mqtt.py +++ b/simpleAPI/simpleAPI_mqtt.py @@ -70,6 +70,7 @@ def _load_config_file(self, config_file: str): self.username = config['username'] self.password = config['password'] self.use_tls = config['use_tls'] + self.validate_cert = config.get('validate_cert', False) except KeyError as e: log.exception(f"Missing required config parameter: {e}") sys.exit(1) @@ -885,6 +886,8 @@ def connect(self): self.client.tls_set(ca_certs=None, certfile=None, keyfile=None, cert_reqs=ssl.CERT_REQUIRED, tls_version=ssl.PROTOCOL_TLS, ciphers=None) + if not self.validate_cert: + self.client.tls_insecure_set(True) # Setup authentication if provided if self.username and self.password: diff --git a/simpleAPI/src/MqttClient.php b/simpleAPI/src/MqttClient.php index 085fc3a75b..22c1f3d2d7 100644 --- a/simpleAPI/src/MqttClient.php +++ b/simpleAPI/src/MqttClient.php @@ -10,6 +10,7 @@ class MqttClient { private $server; private $port; + private $validate_cert; private $username; private $password; private $clientid; @@ -20,7 +21,8 @@ class MqttClient public function __construct($config) { $this->server = $config['mqtt']['server'] ?? 'localhost'; - $this->port = $config['mqtt']['port'] ?? 1883; + $this->port = $config['mqtt']['port'] ?? 8883; + $this->validate_cert = $config['mqtt']['validate_cert'] ?? false; $this->username = $config['mqtt']['username'] ?? ''; $this->password = $config['mqtt']['password'] ?? ''; $this->clientid = $config['mqtt']['clientid'] ?? 'SimpleAPI_' . uniqid(); @@ -114,7 +116,12 @@ private function buildMosquittoCommand($type, $topics, $message = '', $count = n escapeshellarg($this->server), $this->port ); - + + // Zertifikatsvalidierung deaktivieren falls konfiguriert + if (!$this->validate_cert) { + $cmd .= " --insecure"; + } + // Username/Passwort hinzufügen falls konfiguriert if (!empty($this->username)) { $cmd .= sprintf(" -u %s", escapeshellarg($this->username)); From 30b5a7d9f32046a09539c95a4f683a1db923e988 Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Mon, 10 Nov 2025 12:50:30 +0100 Subject: [PATCH 10/76] adopt lxde session --- data/config/display/lxdeautostart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/config/display/lxdeautostart b/data/config/display/lxdeautostart index d230a4ac57..67a625c5c6 100644 --- a/data/config/display/lxdeautostart +++ b/data/config/display/lxdeautostart @@ -1,7 +1,7 @@ -# openwb-version:1 +# openwb-version:2 # enable screen blanking / power management xset s 15 # Start Chromium in kiosk mode sed -i 's/"exited_cleanly":false/"exited_cleanly":true/' ~/.config/chromium/'Local State' sed -i 's/"exited_cleanly":false/"exited_cleanly":true/; s/"exit_type":"[^"]\+"/"exit_type":"Normal"/' ~/.config/chromium/Default/Preferences -chromium --start-fullscreen --kiosk --incognito --noerrdialogs --disable-translate --no-first-run --fast --fast-start --disable-infobars --disable-features=TranslateUI --disk-cache-dir=/dev/null --password-store=basic --disable-pinch --overscroll-history-navigation=disabled --disable-features=TouchpadOverscrollHistoryNavigation http://localhost/openWB/web/display/ +chromium --start-fullscreen --kiosk --incognito --noerrdialogs --disable-translate --no-first-run --fast --fast-start --disable-infobars --disable-features=TranslateUI --disk-cache-dir=/dev/null --password-store=basic --disable-pinch --overscroll-history-navigation=disabled --disable-features=TouchpadOverscrollHistoryNavigation --ignore-certificate-errors --allow-insecure-localhost https://localhost/openWB/web/display/ From f0d5ab8641049916746af26b57e0a7c0bc8fa48b Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Wed, 12 Nov 2025 07:24:05 +0100 Subject: [PATCH 11/76] auth-server --- auth.db | Bin 0 -> 12288 bytes data/config/apache/apache-openwb-ssl.conf | 16 +- data/config/mosquitto/openwb.conf | 6 +- .../auth_service/auth-frontend/.editorconfig | 7 + .../auth_service/auth-frontend/.gitignore | 33 + packages/auth_service/auth-frontend/.npmrc | 5 + .../auth-frontend/.prettierrc.json | 5 + .../auth-frontend/.vscode/extensions.json | 15 + .../auth-frontend/.vscode/settings.json | 9 + packages/auth_service/auth-frontend/README.md | 43 + .../auth-frontend/eslint.config.js | 83 + .../auth_service/auth-frontend/index.html | 24 + .../auth-frontend/package-lock.json | 8311 +++++++++++++++++ .../auth_service/auth-frontend/package.json | 45 + .../auth-frontend/postcss.config.js | 29 + .../auth-frontend/public/favicon.ico | Bin 0 -> 64483 bytes .../public/icons/favicon-128x128.png | Bin 0 -> 12324 bytes .../public/icons/favicon-16x16.png | Bin 0 -> 859 bytes .../public/icons/favicon-32x32.png | Bin 0 -> 2039 bytes .../public/icons/favicon-96x96.png | Bin 0 -> 9643 bytes .../auth-frontend/quasar.config.ts | 217 + .../auth_service/auth-frontend/src/App.vue | 7 + .../src/assets/quasar-logo-vertical.svg | 15 + .../auth-frontend/src/boot/.gitkeep | 0 .../auth-frontend/src/boot/axios.ts | 34 + .../src/components/EssentialLink.vue | 27 + .../auth-frontend/src/components/models.ts | 8 + .../auth-frontend/src/css/app.scss | 1 + .../src/css/quasar.variables.scss | 25 + .../auth_service/auth-frontend/src/env.d.ts | 7 + .../auth-frontend/src/layouts/MainLayout.vue | 106 + .../auth-frontend/src/pages/ErrorNotFound.vue | 23 + .../auth-frontend/src/pages/IndexPage.vue | 8 + .../auth-frontend/src/pages/LoginPage.vue | 64 + .../auth-frontend/src/pages/LogoutPage.vue | 38 + .../auth-frontend/src/router/index.ts | 37 + .../auth-frontend/src/router/routes.ts | 22 + .../auth_service/auth-frontend/tsconfig.json | 3 + packages/auth_service/auth_server.py | 387 + packages/auth_service/init_db.py | 56 + packages/auth_service/requirements.txt | 5 + 41 files changed, 9719 insertions(+), 2 deletions(-) create mode 100644 auth.db create mode 100644 packages/auth_service/auth-frontend/.editorconfig create mode 100644 packages/auth_service/auth-frontend/.gitignore create mode 100644 packages/auth_service/auth-frontend/.npmrc create mode 100644 packages/auth_service/auth-frontend/.prettierrc.json create mode 100644 packages/auth_service/auth-frontend/.vscode/extensions.json create mode 100644 packages/auth_service/auth-frontend/.vscode/settings.json create mode 100644 packages/auth_service/auth-frontend/README.md create mode 100644 packages/auth_service/auth-frontend/eslint.config.js create mode 100644 packages/auth_service/auth-frontend/index.html create mode 100644 packages/auth_service/auth-frontend/package-lock.json create mode 100644 packages/auth_service/auth-frontend/package.json create mode 100644 packages/auth_service/auth-frontend/postcss.config.js create mode 100644 packages/auth_service/auth-frontend/public/favicon.ico create mode 100644 packages/auth_service/auth-frontend/public/icons/favicon-128x128.png create mode 100644 packages/auth_service/auth-frontend/public/icons/favicon-16x16.png create mode 100644 packages/auth_service/auth-frontend/public/icons/favicon-32x32.png create mode 100644 packages/auth_service/auth-frontend/public/icons/favicon-96x96.png create mode 100644 packages/auth_service/auth-frontend/quasar.config.ts create mode 100644 packages/auth_service/auth-frontend/src/App.vue create mode 100644 packages/auth_service/auth-frontend/src/assets/quasar-logo-vertical.svg create mode 100644 packages/auth_service/auth-frontend/src/boot/.gitkeep create mode 100644 packages/auth_service/auth-frontend/src/boot/axios.ts create mode 100644 packages/auth_service/auth-frontend/src/components/EssentialLink.vue create mode 100644 packages/auth_service/auth-frontend/src/components/models.ts create mode 100644 packages/auth_service/auth-frontend/src/css/app.scss create mode 100644 packages/auth_service/auth-frontend/src/css/quasar.variables.scss create mode 100644 packages/auth_service/auth-frontend/src/env.d.ts create mode 100644 packages/auth_service/auth-frontend/src/layouts/MainLayout.vue create mode 100644 packages/auth_service/auth-frontend/src/pages/ErrorNotFound.vue create mode 100644 packages/auth_service/auth-frontend/src/pages/IndexPage.vue create mode 100644 packages/auth_service/auth-frontend/src/pages/LoginPage.vue create mode 100644 packages/auth_service/auth-frontend/src/pages/LogoutPage.vue create mode 100644 packages/auth_service/auth-frontend/src/router/index.ts create mode 100644 packages/auth_service/auth-frontend/src/router/routes.ts create mode 100644 packages/auth_service/auth-frontend/tsconfig.json create mode 100644 packages/auth_service/auth_server.py create mode 100644 packages/auth_service/init_db.py create mode 100644 packages/auth_service/requirements.txt diff --git a/auth.db b/auth.db new file mode 100644 index 0000000000000000000000000000000000000000..8f0e07118accd244f57b6cedad573f3661a34874 GIT binary patch literal 12288 zcmeI$O;g%H7y#f+)M_0Sr!x-iZ4Wxuu>uKYTAXplh^wM}CZt{7~%CpF^v)@pB7`^khmnHB{}x_p$X6r0w4eaAOHd&00JNY0w4eaAn>;c ze0VC%#^Z6}V~pu7iv~XR{HPLh6{4sFtIA%1;HU{dpT~DWZQZo6O6n>;t>lYJrGZaK zls>C_q(^_N@W$7YK6jhP{;Iqra8JzqY>i{OaFbl=UTTz@h}5kW_x1lNt|hyS7aoHnEP;Q!w{}I)Cic=ylKZsIT#T zx0)}Ks;U%E@8$QX&ZzNI?`ZA0TBSltsy3PzF>Y*#kK#LV0hx|Lul>HoclMedFgLo^ zqBo*R(O0;yp9}v{i@b2eZP$=3oY)_}mV^uWs0; zvun9+-RinNySugAv>Ua0Ju4;K$M0_v@7@q5B?Fo=%95Q?+D9HcV3u@7_KfUBr}^r2 z{ ServerAdmin webmaster@localhost @@ -147,6 +147,20 @@ # ToDo: remove /mqtt target once all clients use /ws ProxyPassMatch "^/(ws|mqtt)(/|$)" "wss://127.0.0.1:9002/" + # Auth-Service-Proxy + + ProxyPass http://127.0.0.1:3000/ + ProxyPassReverse http://127.0.0.1:3000/ + + # Optional: Header durchreichen, falls Auth-Service sie braucht + RequestHeader set X-Forwarded-Proto "https" + RequestHeader set X-Forwarded-Port "443" + + # Sicherheit (keine Directory Listings etc.) + Options -Indexes + Require all granted + + diff --git a/data/config/mosquitto/openwb.conf b/data/config/mosquitto/openwb.conf index 8f3402f20a..5290fe952c 100644 --- a/data/config/mosquitto/openwb.conf +++ b/data/config/mosquitto/openwb.conf @@ -1,4 +1,4 @@ -# openwb-version:4 +# openwb-version:5 # public secure websocket listener listener 9002 @@ -7,6 +7,8 @@ allow_anonymous true certfile /etc/mosquitto/certs/openwb.pem keyfile /etc/mosquitto/certs/openwb.key acl_file /etc/mosquitto/mosquitto.acl +#plugin /usr/lib/x86_64-linux-gnu/mosquitto_dynamic_security.so +#plugin_opt_config_file /var/lib/mosquitto/dynamic_security.json # local bridge listener listener 1884 localhost @@ -20,3 +22,5 @@ allow_anonymous true certfile /etc/mosquitto/certs/openwb.pem keyfile /etc/mosquitto/certs/openwb.key acl_file /etc/mosquitto/mosquitto.acl +#plugin /usr/lib/x86_64-linux-gnu/mosquitto_dynamic_security.so +#plugin_opt_config_file /var/lib/mosquitto/dynamic_security.json diff --git a/packages/auth_service/auth-frontend/.editorconfig b/packages/auth_service/auth-frontend/.editorconfig new file mode 100644 index 0000000000..f654551630 --- /dev/null +++ b/packages/auth_service/auth-frontend/.editorconfig @@ -0,0 +1,7 @@ +[*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,vue}] +charset = utf-8 +indent_size = 2 +indent_style = space +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/packages/auth_service/auth-frontend/.gitignore b/packages/auth_service/auth-frontend/.gitignore new file mode 100644 index 0000000000..f1d913c8dc --- /dev/null +++ b/packages/auth_service/auth-frontend/.gitignore @@ -0,0 +1,33 @@ +.DS_Store +.thumbs.db +node_modules + +# Quasar core related directories +.quasar +/dist +/quasar.config.*.temporary.compiled* + +# Cordova related directories and files +/src-cordova/node_modules +/src-cordova/platforms +/src-cordova/plugins +/src-cordova/www + +# Capacitor related directories and files +/src-capacitor/www +/src-capacitor/node_modules + +# Log files +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Editor directories and files +.idea +*.suo +*.ntvs* +*.njsproj +*.sln + +# local .env files +.env.local* diff --git a/packages/auth_service/auth-frontend/.npmrc b/packages/auth_service/auth-frontend/.npmrc new file mode 100644 index 0000000000..eb19082827 --- /dev/null +++ b/packages/auth_service/auth-frontend/.npmrc @@ -0,0 +1,5 @@ +# pnpm-related options +shamefully-hoist=true +strict-peer-dependencies=false +# to get the latest compatible packages when creating the project https://github.com/pnpm/pnpm/issues/6463 +resolution-mode=highest diff --git a/packages/auth_service/auth-frontend/.prettierrc.json b/packages/auth_service/auth-frontend/.prettierrc.json new file mode 100644 index 0000000000..ca848b72d9 --- /dev/null +++ b/packages/auth_service/auth-frontend/.prettierrc.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://json.schemastore.org/prettierrc", + "singleQuote": true, + "printWidth": 100 +} diff --git a/packages/auth_service/auth-frontend/.vscode/extensions.json b/packages/auth_service/auth-frontend/.vscode/extensions.json new file mode 100644 index 0000000000..131b75d285 --- /dev/null +++ b/packages/auth_service/auth-frontend/.vscode/extensions.json @@ -0,0 +1,15 @@ +{ + "recommendations": [ + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "editorconfig.editorconfig", + "vue.volar", + "wayou.vscode-todo-highlight" + ], + "unwantedRecommendations": [ + "octref.vetur", + "hookyqr.beautify", + "dbaeumer.jshint", + "ms-vscode.vscode-typescript-tslint-plugin" + ] +} diff --git a/packages/auth_service/auth-frontend/.vscode/settings.json b/packages/auth_service/auth-frontend/.vscode/settings.json new file mode 100644 index 0000000000..a62026acf1 --- /dev/null +++ b/packages/auth_service/auth-frontend/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "editor.bracketPairColorization.enabled": true, + "editor.guides.bracketPairs": true, + "editor.formatOnSave": true, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.codeActionsOnSave": ["source.fixAll.eslint"], + "eslint.validate": ["javascript", "javascriptreact", "typescript", "vue"], + "typescript.tsdk": "node_modules/typescript/lib" +} diff --git a/packages/auth_service/auth-frontend/README.md b/packages/auth_service/auth-frontend/README.md new file mode 100644 index 0000000000..0813a8fac5 --- /dev/null +++ b/packages/auth_service/auth-frontend/README.md @@ -0,0 +1,43 @@ +# openWB Auth Frontend (openwb-auth-frontend) + +Authentication frontend for openWB + +## Install the dependencies + +```bash +yarn +# or +npm install +``` + +### Start the app in development mode (hot-code reloading, error reporting, etc.) + +```bash +quasar dev +``` + +### Lint the files + +```bash +yarn lint +# or +npm run lint +``` + +### Format the files + +```bash +yarn format +# or +npm run format +``` + +### Build the app for production + +```bash +quasar build +``` + +### Customize the configuration + +See [Configuring quasar.config.js](https://v2.quasar.dev/quasar-cli-vite/quasar-config-js). diff --git a/packages/auth_service/auth-frontend/eslint.config.js b/packages/auth_service/auth-frontend/eslint.config.js new file mode 100644 index 0000000000..8515d73927 --- /dev/null +++ b/packages/auth_service/auth-frontend/eslint.config.js @@ -0,0 +1,83 @@ +import js from '@eslint/js'; +import globals from 'globals'; +import pluginVue from 'eslint-plugin-vue'; +import pluginQuasar from '@quasar/app-vite/eslint'; +import { defineConfigWithVueTs, vueTsConfigs } from '@vue/eslint-config-typescript'; +import prettierSkipFormatting from '@vue/eslint-config-prettier/skip-formatting'; + +export default defineConfigWithVueTs( + { + /** + * Ignore the following files. + * Please note that pluginQuasar.configs.recommended() already ignores + * the "node_modules" folder for you (and all other Quasar project + * relevant folders and files). + * + * ESLint requires "ignores" key to be the only one in this object + */ + // ignores: [] + }, + + pluginQuasar.configs.recommended(), + js.configs.recommended, + + /** + * https://eslint.vuejs.org + * + * pluginVue.configs.base + * -> Settings and rules to enable correct ESLint parsing. + * pluginVue.configs[ 'flat/essential'] + * -> base, plus rules to prevent errors or unintended behavior. + * pluginVue.configs["flat/strongly-recommended"] + * -> Above, plus rules to considerably improve code readability and/or dev experience. + * pluginVue.configs["flat/recommended"] + * -> Above, plus rules to enforce subjective community defaults to ensure consistency. + */ + pluginVue.configs['flat/essential'], + + { + files: ['**/*.ts', '**/*.vue'], + rules: { + '@typescript-eslint/consistent-type-imports': ['error', { prefer: 'type-imports' }], + }, + }, + // https://github.com/vuejs/eslint-config-typescript + vueTsConfigs.recommendedTypeChecked, + + { + languageOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + + globals: { + ...globals.browser, + ...globals.node, // SSR, Electron, config files + process: 'readonly', // process.env.* + ga: 'readonly', // Google Analytics + cordova: 'readonly', + Capacitor: 'readonly', + chrome: 'readonly', // BEX related + browser: 'readonly', // BEX related + }, + }, + + // add your custom rules here + rules: { + 'prefer-promise-reject-errors': 'off', + + // allow debugger during development only + 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', + }, + }, + + { + files: ['src-pwa/custom-service-worker.ts'], + languageOptions: { + globals: { + ...globals.serviceworker, + }, + }, + }, + + prettierSkipFormatting, +); diff --git a/packages/auth_service/auth-frontend/index.html b/packages/auth_service/auth-frontend/index.html new file mode 100644 index 0000000000..8caf416465 --- /dev/null +++ b/packages/auth_service/auth-frontend/index.html @@ -0,0 +1,24 @@ + + + + <%= productName %> + + + + + + + + + + + + + + + + + diff --git a/packages/auth_service/auth-frontend/package-lock.json b/packages/auth_service/auth-frontend/package-lock.json new file mode 100644 index 0000000000..7e10e8ec36 --- /dev/null +++ b/packages/auth_service/auth-frontend/package-lock.json @@ -0,0 +1,8311 @@ +{ + "name": "openwb-auth-frontend", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "openwb-auth-frontend", + "version": "0.0.1", + "hasInstallScript": true, + "dependencies": { + "@quasar/extras": "^1.16.4", + "axios": "^1.2.1", + "quasar": "^2.16.0", + "vue": "^3.5.22", + "vue-router": "^4.0.12" + }, + "devDependencies": { + "@eslint/js": "^9.14.0", + "@quasar/app-vite": "^2.1.0", + "@types/node": "^20.5.9", + "@vue/eslint-config-prettier": "^10.1.0", + "@vue/eslint-config-typescript": "^14.4.0", + "autoprefixer": "^10.4.2", + "eslint": "^9.14.0", + "eslint-plugin-vue": "^10.4.0", + "globals": "^16.4.0", + "prettier": "^3.3.3", + "typescript": "^5.9.2", + "vite-plugin-checker": "^0.11.0", + "vue-eslint-parser": "^10.2.0", + "vue-tsc": "^3.0.7" + }, + "engines": { + "node": "^28 || ^26 || ^24 || ^22 || ^20", + "npm": ">= 6.13.4", + "yarn": ">= 1.21.1" + } + }, + "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": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.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==", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.5" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.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==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bufbuild/protobuf": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.10.0.tgz", + "integrity": "sha512-fdRs9PSrBF7QUntpZpq6BTw58fhgGJojgg39m9oFOJGZT+nip9b0so5cYY1oWl5pvemDLr0cPPsH46vwThEbpQ==", + "dev": true, + "license": "(Apache-2.0 AND BSD-3-Clause)" + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "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": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "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.7", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/config-helpers": { + "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.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": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "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": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "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": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "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.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@inquirer/external-editor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.3.tgz", + "integrity": "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chardet": "^2.1.1", + "iconv-lite": "^0.7.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/external-editor/node_modules/iconv-lite": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", + "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@inquirer/figures": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.15.tgz", + "integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "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": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@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", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "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": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@parcel/watcher": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz", + "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^1.0.3", + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "node-addon-api": "^7.0.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.1", + "@parcel/watcher-darwin-arm64": "2.5.1", + "@parcel/watcher-darwin-x64": "2.5.1", + "@parcel/watcher-freebsd-x64": "2.5.1", + "@parcel/watcher-linux-arm-glibc": "2.5.1", + "@parcel/watcher-linux-arm-musl": "2.5.1", + "@parcel/watcher-linux-arm64-glibc": "2.5.1", + "@parcel/watcher-linux-arm64-musl": "2.5.1", + "@parcel/watcher-linux-x64-glibc": "2.5.1", + "@parcel/watcher-linux-x64-musl": "2.5.1", + "@parcel/watcher-win32-arm64": "2.5.1", + "@parcel/watcher-win32-ia32": "2.5.1", + "@parcel/watcher-win32-x64": "2.5.1" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz", + "integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz", + "integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz", + "integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz", + "integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz", + "integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz", + "integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz", + "integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz", + "integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz", + "integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz", + "integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz", + "integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz", + "integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz", + "integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pkgr/core": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" + } + }, + "node_modules/@quasar/app-vite": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@quasar/app-vite/-/app-vite-2.4.0.tgz", + "integrity": "sha512-nfdcfERQ1bdUFsgXfYexgUAGBrsRHuzlik5p58cKGpYXiwUZZN6mJhN8VxU/zGT0GYHHiNIZlb67N+R52NYd6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@quasar/render-ssr-error": "^1.0.3", + "@quasar/ssl-certificate": "^1.0.0", + "@quasar/vite-plugin": "^1.10.0", + "@types/chrome": "^0.0.262", + "@types/compression": "^1.7.5", + "@types/cordova": "^11.0.3", + "@types/express": "^4.17.21", + "@vitejs/plugin-vue": "^6.0.1", + "archiver": "^7.0.1", + "chokidar": "^3.6.0", + "ci-info": "^4.0.0", + "compression": "^1.7.5", + "confbox": "^0.1.8", + "cross-spawn": "^7.0.6", + "dot-prop": "9.0.0", + "dotenv": "^16.4.5", + "dotenv-expand": "^11.0.6", + "elementtree": "0.1.7", + "esbuild": "^0.25.0", + "express": "^4.21.2", + "fs-extra": "^11.2.0", + "html-minifier-terser": "^7.2.0", + "inquirer": "^9.3.7", + "isbinaryfile": "^5.0.4", + "kolorist": "^1.8.0", + "lodash": "^4.17.21", + "minimist": "^1.2.8", + "mlly": "^1.7.4", + "open": "^10.1.0", + "rollup-plugin-visualizer": "^5.13.1", + "sass-embedded": "^1.83.0", + "semver": "^7.6.3", + "serialize-javascript": "^6.0.2", + "tinyglobby": "^0.2.10", + "ts-essentials": "^9.4.2", + "vite": "^7.0.3", + "webpack-merge": "^6.0.1" + }, + "bin": { + "quasar": "bin/quasar.js" + }, + "engines": { + "node": "^30 || ^28 || ^26 || ^24 || ^22 || ^20", + "npm": ">= 6.14.12", + "yarn": ">= 1.17.3" + }, + "funding": { + "type": "github", + "url": "https://donate.quasar.dev" + }, + "peerDependencies": { + "@electron/packager": ">= 18", + "electron-builder": ">= 22", + "pinia": "^2.0.0 || ^3.0.0", + "quasar": "^2.16.0", + "typescript": ">= 5.4", + "vue": "^3.2.29", + "vue-router": "^4.0.12", + "workbox-build": ">= 6" + }, + "peerDependenciesMeta": { + "@electron/packager": { + "optional": true + }, + "electron-builder": { + "optional": true + }, + "eslint": { + "optional": true + }, + "pinia": { + "optional": true + }, + "typescript": { + "optional": true + }, + "workbox-build": { + "optional": true + } + } + }, + "node_modules/@quasar/extras": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@quasar/extras/-/extras-1.17.0.tgz", + "integrity": "sha512-KqAHdSJfIDauiR1nJ8rqHWT0diqD0QradZKoVIZJAilHAvgwyPIY7MbyR2z4RIMkUIMUSqBZcbshMpEw+9A30w==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://donate.quasar.dev" + } + }, + "node_modules/@quasar/render-ssr-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@quasar/render-ssr-error/-/render-ssr-error-1.0.3.tgz", + "integrity": "sha512-A8RF99q6/sOSe1Ighnh5syEIbliD3qUYEJd2HyfFyBPSMF+WYGXon5dmzg4nUoK662NgOggInevkDyBDJcZugg==", + "dev": true, + "license": "MIT", + "dependencies": { + "stack-trace": "^1.0.0-pre2" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "type": "github", + "url": "https://donate.quasar.dev" + } + }, + "node_modules/@quasar/ssl-certificate": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@quasar/ssl-certificate/-/ssl-certificate-1.0.0.tgz", + "integrity": "sha512-RhZF7rO76T7Ywer1/5lCe7xl3CIiXxSAH1xgwOj0wcHTityDxJqIN/5YIj6BxMvlFw8XkJDoB1udEQafoVFA4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fs-extra": "^11.1.1", + "selfsigned": "^2.1.1" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "type": "github", + "url": "https://donate.quasar.dev" + } + }, + "node_modules/@quasar/vite-plugin": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@quasar/vite-plugin/-/vite-plugin-1.10.0.tgz", + "integrity": "sha512-4PJoTclz4ZjAfyqe0+hlkKcFJt0e2NX3Ac3hy8ILqUPdtZ24nCo5/xEHvTxZGBQMKRPwwePbO8CVs4n9EKJEug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "type": "github", + "url": "https://donate.quasar.dev" + }, + "peerDependencies": { + "@vitejs/plugin-vue": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0", + "quasar": "^2.16.0", + "vite": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0", + "vue": "^3.0.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.29", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.29.tgz", + "integrity": "sha512-NIJgOsMjbxAXvoGq/X0gD7VPMQ8j9g0BiDaNjVNVjvl+iKXxL3Jre0v31RmBYeLEmkbj2s02v8vFTbUXi5XS2Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "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.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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "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.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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/chrome": { + "version": "0.0.262", + "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.262.tgz", + "integrity": "sha512-TOoj3dqSYE13PD2fRuMQ6X6pggEvL9rRk/yOYOyWE6sfqRWxsJm4VoVm+wr9pkr4Sht/M5t7FFL4vXato8d1gA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/filesystem": "*", + "@types/har-format": "*" + } + }, + "node_modules/@types/compression": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@types/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-kCFuWS0ebDbmxs0AXYn6e2r2nrGAb5KwQhknjSPSPgJcGd8+HVSILlUyFhGqML2gk39HcG7D1ydW9/qpYkN00Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cordova": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@types/cordova/-/cordova-11.0.3.tgz", + "integrity": "sha512-kyuRQ40/NWQVhqGIHq78Ehu2Bf9Mlg0LhmSmis6ZFJK7z933FRfYi8tHe/k/0fB+PGfCf95rJC6TO7dopaFvAg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "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" + }, + "node_modules/@types/express": { + "version": "4.17.25", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz", + "integrity": "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "^1" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.7", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.7.tgz", + "integrity": "sha512-FvPtiIf1LfhzsaIXhv/PHan/2FeQBbtBDtfX2QfvPxdUelMDEckK08SM6nqo1MIZY3RUlfA+HV8+hFUSio78qg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/filesystem": { + "version": "0.0.36", + "resolved": "https://registry.npmjs.org/@types/filesystem/-/filesystem-0.0.36.tgz", + "integrity": "sha512-vPDXOZuannb9FZdxgHnqSwAG/jvdGM8Wq+6N4D/d80z+D4HWH+bItqsZaVRQykAn6WEVeEkLm2oQigyHtgb0RA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/filewriter": "*" + } + }, + "node_modules/@types/filewriter": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/@types/filewriter/-/filewriter-0.0.33.tgz", + "integrity": "sha512-xFU8ZXTw4gd358lb2jw25nxY9QAgqn2+bKKjKOYfNCzN4DKCFetK7sPtrlpg66Ywe3vWY9FNxprZawAh9wfJ3g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/har-format": { + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@types/har-format/-/har-format-1.2.16.tgz", + "integrity": "sha512-fluxdy7ryD3MV6h8pTfTYpy/xQzCFC7m89nOH9y94cNqJ1mDIDPut7MnRHI3F6qRmh/cT2fUjG1MLdCNb4hE9A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.19.24", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.24.tgz", + "integrity": "sha512-FE5u0ezmi6y9OZEzlJfg37mqqf6ZDSF2V/NLjUyGrR9uTZ7Sb9F7bLNZ03S4XVUNRWGA7Ck4c1kK+YnuWjl+DA==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.14.tgz", + "integrity": "sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", + "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz", + "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "<1" + } + }, + "node_modules/@types/serve-static/node_modules/@types/send": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz", + "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "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.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", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.46.4", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "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", + "dependencies": { + "@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": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "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.46.4", + "@typescript-eslint/types": "^8.46.4", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "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.46.4", + "@typescript-eslint/visitor-keys": "8.46.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "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": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "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.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" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "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": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "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.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", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/utils": { + "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.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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "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.46.4", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@vitejs/plugin-vue": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.1.tgz", + "integrity": "sha512-+MaE752hU0wfPFJEUAIxqw18+20euHHdxVtMvbFcOEpjEyfqXH/5DCoTHiVJ0J29EhTJdoTkjEv5YBKU9dnoTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rolldown/pluginutils": "1.0.0-beta.29" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@volar/language-core": { + "version": "2.4.23", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.23.tgz", + "integrity": "sha512-hEEd5ET/oSmBC6pi1j6NaNYRWoAiDhINbT8rmwtINugR39loROSlufGdYMF9TaKGfz+ViGs1Idi3mAhnuPcoGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/source-map": "2.4.23" + } + }, + "node_modules/@volar/source-map": { + "version": "2.4.23", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.23.tgz", + "integrity": "sha512-Z1Uc8IB57Lm6k7q6KIDu/p+JWtf3xsXJqAX/5r18hYOTpJyBn0KXUR8oTJ4WFYOcDzWC9n3IflGgHowx6U6z9Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@volar/typescript": { + "version": "2.4.23", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.23.tgz", + "integrity": "sha512-lAB5zJghWxVPqfcStmAP1ZqQacMpe90UrP5RJ3arDyrhy4aCUQqmxPPLB2PWDKugvylmO41ljK7vZ+t6INMTag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.23", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.24", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.24.tgz", + "integrity": "sha512-eDl5H57AOpNakGNAkFDH+y7kTqrQpJkZFXhWZQGyx/5Wh7B1uQYvcWkvZi11BDhscPgj8N7XV3oRwiPnx1Vrig==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "@vue/shared": "3.5.24", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.24", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.24.tgz", + "integrity": "sha512-1QHGAvs53gXkWdd3ZMGYuvQFXHW4ksKWPG8HP8/2BscrbZ0brw183q2oNWjMrSWImYLHxHrx1ItBQr50I/q2zw==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.24", + "@vue/shared": "3.5.24" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.24", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.24.tgz", + "integrity": "sha512-8EG5YPRgmTB+YxYBM3VXy8zHD9SWHUJLIGPhDovo3Z8VOgvP+O7UP5vl0J4BBPWYD9vxtBabzW1EuEZ+Cqs14g==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "@vue/compiler-core": "3.5.24", + "@vue/compiler-dom": "3.5.24", + "@vue/compiler-ssr": "3.5.24", + "@vue/shared": "3.5.24", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.6", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.24", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.24.tgz", + "integrity": "sha512-trOvMWNBMQ/odMRHW7Ae1CdfYx+7MuiQu62Jtu36gMLXcaoqKvAyh+P73sYG9ll+6jLB6QPovqoKGGZROzkFFg==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.24", + "@vue/shared": "3.5.24" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "license": "MIT" + }, + "node_modules/@vue/eslint-config-prettier": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/@vue/eslint-config-prettier/-/eslint-config-prettier-10.2.0.tgz", + "integrity": "sha512-GL3YBLwv/+b86yHcNNfPJxOTtVFJ4Mbc9UU3zR+KVoG7SwGTjPT+32fXamscNumElhcpXW3mT0DgzS9w32S7Bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-config-prettier": "^10.0.1", + "eslint-plugin-prettier": "^5.2.2" + }, + "peerDependencies": { + "eslint": ">= 8.21.0", + "prettier": ">= 3.0.0" + } + }, + "node_modules/@vue/eslint-config-typescript": { + "version": "14.6.0", + "resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-14.6.0.tgz", + "integrity": "sha512-UpiRY/7go4Yps4mYCjkvlIbVWmn9YvPGQDxTAlcKLphyaD77LjIu3plH4Y9zNT0GB4f3K5tMmhhtRhPOgrQ/bQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "^8.35.1", + "fast-glob": "^3.3.3", + "typescript-eslint": "^8.35.1", + "vue-eslint-parser": "^10.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "eslint": "^9.10.0", + "eslint-plugin-vue": "^9.28.0 || ^10.0.0", + "typescript": ">=4.8.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@vue/language-core": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-3.1.3.tgz", + "integrity": "sha512-KpR1F/eGAG9D1RZ0/T6zWJs6dh/pRLfY5WupecyYKJ1fjVmDMgTPw9wXmKv2rBjo4zCJiOSiyB8BDP1OUwpMEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.23", + "@vue/compiler-dom": "^3.5.0", + "@vue/shared": "^3.5.0", + "alien-signals": "^3.0.0", + "muggle-string": "^0.4.1", + "path-browserify": "^1.0.1", + "picomatch": "^4.0.2" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@vue/language-core/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.24", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.24.tgz", + "integrity": "sha512-BM8kBhtlkkbnyl4q+HiF5R5BL0ycDPfihowulm02q3WYp2vxgPcJuZO866qa/0u3idbMntKEtVNuAUp5bw4teg==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.24" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.24", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.24.tgz", + "integrity": "sha512-RYP/byyKDgNIqfX/gNb2PB55dJmM97jc9wyF3jK7QUInYKypK2exmZMNwnjueWwGceEkP6NChd3D2ZVEp9undQ==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.24", + "@vue/shared": "3.5.24" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.24", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.24.tgz", + "integrity": "sha512-Z8ANhr/i0XIluonHVjbUkjvn+CyrxbXRIxR7wn7+X7xlcb7dJsfITZbkVOeJZdP8VZwfrWRsWdShH6pngMxRjw==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.24", + "@vue/runtime-core": "3.5.24", + "@vue/shared": "3.5.24", + "csstype": "^3.1.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.24", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.24.tgz", + "integrity": "sha512-Yh2j2Y4G/0/4z/xJ1Bad4mxaAk++C2v4kaa8oSYTMJBJ00/ndPuxCnWeot0/7/qafQFLh5pr6xeV6SdMcE/G1w==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.24", + "@vue/shared": "3.5.24" + }, + "peerDependencies": { + "vue": "3.5.24" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.24", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.24.tgz", + "integrity": "sha512-9cwHL2EsJBdi8NY22pngYYWzkTDhld6fAD6jlaeloNGciNSJL6bLpbxVgXl96X00Jtc6YWQv96YA/0sxex/k1A==", + "license": "MIT" + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dev": true, + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/alien-signals": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/alien-signals/-/alien-signals-3.1.0.tgz", + "integrity": "sha512-yufC6VpSy8tK3I0lO67pjumo5JvDQVQyr38+3OHqe6CHl1t2VZekKZ7EKKZSqk0cRmE7U7tfZbpXiKNzuc+ckg==", + "dev": true, + "license": "MIT" + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/archiver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-7.0.1.tgz", + "integrity": "sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "archiver-utils": "^5.0.2", + "async": "^3.2.4", + "buffer-crc32": "^1.0.0", + "readable-stream": "^4.0.0", + "readdir-glob": "^1.1.2", + "tar-stream": "^3.0.0", + "zip-stream": "^6.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/archiver-utils": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-5.0.2.tgz", + "integrity": "sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob": "^10.0.0", + "graceful-fs": "^4.2.0", + "is-stream": "^2.0.1", + "lazystream": "^1.0.0", + "lodash": "^4.17.15", + "normalize-path": "^3.0.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/autoprefixer": { + "version": "10.4.22", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.22.tgz", + "integrity": "sha512-ARe0v/t9gO28Bznv6GgqARmVqcWOV3mfgUPn9becPHMiD3o9BwlRgaeccZnwTpZ7Zwqrm+c1sUSsMxIzQzc8Xg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.27.0", + "caniuse-lite": "^1.0.30001754", + "fraction.js": "^5.3.4", + "normalize-range": "^0.1.2", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/axios": { + "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", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/b4a": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.7.3.tgz", + "integrity": "sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q==", + "dev": true, + "license": "Apache-2.0", + "peerDependencies": { + "react-native-b4a": "*" + }, + "peerDependenciesMeta": { + "react-native-b4a": { + "optional": true + } + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/bare-events": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz", + "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==", + "dev": true, + "license": "Apache-2.0", + "peerDependencies": { + "bare-abort-controller": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + } + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.8.25", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.25.tgz", + "integrity": "sha512-2NovHVesVF5TXefsGX1yzx1xgr7+m9JQenvz6FQY3qd+YXkKkYiv+vTCc7OriP9mcDZpTC5mAOYN4ocd29+erA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "license": "ISC" + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "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", + "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/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-builder": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/buffer-builder/-/buffer-builder-0.2.0.tgz", + "integrity": "sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==", + "dev": true, + "license": "MIT/X11" + }, + "node_modules/buffer-crc32": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", + "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001754", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001754.tgz", + "integrity": "sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg==", + "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", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chardet": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.1.tgz", + "integrity": "sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/ci-info": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", + "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/clean-css": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 12" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/colorjs.io": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/colorjs.io/-/colorjs.io-0.5.2.tgz", + "integrity": "sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/compress-commons": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz", + "integrity": "sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "crc-32": "^1.2.0", + "crc32-stream": "^6.0.0", + "is-stream": "^2.0.1", + "normalize-path": "^3.0.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "compressible": "~2.0.18", + "debug": "2.6.9", + "negotiator": "~0.6.4", + "on-headers": "~1.1.0", + "safe-buffer": "5.2.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/crc32-stream": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-6.0.0.tgz", + "integrity": "sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==", + "dev": true, + "license": "MIT", + "dependencies": { + "crc-32": "^1.2.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/default-browser": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", + "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", + "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dot-prop": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-9.0.0.tgz", + "integrity": "sha512-1gxPBJpI/pcjQhKgIU91II6Wkay+dLcN3M6rf2uwP8hRur3HtQXjVrdAK3sjC0piaEuxzMwjXChcETiJl47lAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^4.18.2" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dotenv-expand": { + "version": "11.0.7", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.7.tgz", + "integrity": "sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dotenv": "^16.4.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.250", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.250.tgz", + "integrity": "sha512-/5UMj9IiGDMOFBnN4i7/Ry5onJrAGSbOGo3s9FEKmwobGq6xw832ccET0CE3CkkMBZ8GJSlUIesZofpyurqDXw==", + "dev": true, + "license": "ISC" + }, + "node_modules/elementtree": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/elementtree/-/elementtree-0.1.7.tgz", + "integrity": "sha512-wkgGT6kugeQk/P6VZ/f4T+4HB41BVgNBq5CDIZVbQ02nvTVqAiVTbskxxu3eA/X96lMlfYOwnLQpN2v5E1zDEg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "sax": "1.1.4" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, + "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-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true, + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz", + "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@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.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", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-prettier": { + "version": "10.1.8", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", + "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.4.tgz", + "integrity": "sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.11.7" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-vue": { + "version": "10.5.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-10.5.1.tgz", + "integrity": "sha512-SbR9ZBUFKgvWAbq3RrdCtWaW0IKm6wwUiApxf3BVTNfqUIo4IQQmreMg2iHFJJ6C/0wss3LXURBJ1OwS/MhFcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "natural-compare": "^1.4.0", + "nth-check": "^2.1.1", + "postcss-selector-parser": "^6.0.15", + "semver": "^7.6.3", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "@stylistic/eslint-plugin": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0", + "@typescript-eslint/parser": "^7.0.0 || ^8.0.0", + "eslint": "^8.57.0 || ^9.0.0", + "vue-eslint-parser": "^10.0.0" + }, + "peerDependenciesMeta": { + "@stylistic/eslint-plugin": { + "optional": true + }, + "@typescript-eslint/parser": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/events-universal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", + "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bare-events": "^2.7.0" + } + }, + "node_modules/express": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.12", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.2.tgz", + "integrity": "sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "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": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/html-minifier-terser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz", + "integrity": "sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "~5.3.2", + "commander": "^10.0.0", + "entities": "^4.4.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.15.1" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/immutable": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.4.tgz", + "integrity": "sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA==", + "dev": true, + "license": "MIT" + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/inquirer": { + "version": "9.3.8", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.3.8.tgz", + "integrity": "sha512-pFGGdaHrmRKMh4WoDDSowddgjT1Vkl90atobmTeSmcPGdYiwikch/m/Ef5wRaiamHejtw0cUUMMerzDUXCci2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/external-editor": "^1.0.2", + "@inquirer/figures": "^1.0.3", + "ansi-escapes": "^4.3.2", + "cli-width": "^4.1.0", + "mute-stream": "1.0.0", + "ora": "^5.4.1", + "run-async": "^3.0.0", + "rxjs": "^7.8.1", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/isbinaryfile": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.6.tgz", + "integrity": "sha512-I+NmIfBHUl+r2wcDd6JwE9yWje/PIVY/R5/CmV8dXLZd5K+L9X2klAOwfAHNnondLXkbHyTAleQAWonpTJBTtw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kolorist": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", + "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/lazystream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/lazystream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/lazystream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "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", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/mlly": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz", + "integrity": "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.15.0", + "pathe": "^2.0.3", + "pkg-types": "^1.3.1", + "ufo": "^1.6.1" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/muggle-string": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/mute-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "dev": true, + "license": "(BSD-3-Clause OR GPL-2.0)", + "engines": { + "node": ">= 6.13.0" + } + }, + "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/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", + "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0", + "unicorn-magic": "^0.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", + "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "wsl-utils": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkg-types": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/quasar": { + "version": "2.18.5", + "resolved": "https://registry.npmjs.org/quasar/-/quasar-2.18.5.tgz", + "integrity": "sha512-5ItDSsNjqBVRrC7SqcdvT1F5mghVyJ/KmaWNwnaT5mM91a7gWpT/d7wTCIFxxDbWLZdkHKI+cpdudEqnfcSw9A==", + "license": "MIT", + "engines": { + "node": ">= 10.18.1", + "npm": ">= 6.13.4", + "yarn": ">= 1.21.1" + }, + "funding": { + "type": "github", + "url": "https://donate.quasar.dev" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "dev": true, + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/readable-stream/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/readdir-glob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", + "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.1.0" + } + }, + "node_modules/readdir-glob/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rollup": { + "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.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@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" + } + }, + "node_modules/rollup-plugin-visualizer": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-visualizer/-/rollup-plugin-visualizer-5.14.0.tgz", + "integrity": "sha512-VlDXneTDaKsHIw8yzJAFWtrzguoJ/LnQ+lMpoVfYJ3jJF4Ihe5oYLAqLklIK/35lgUY+1yEzCkHyZ1j4A5w5fA==", + "dev": true, + "license": "MIT", + "dependencies": { + "open": "^8.4.0", + "picomatch": "^4.0.2", + "source-map": "^0.7.4", + "yargs": "^17.5.1" + }, + "bin": { + "rollup-plugin-visualizer": "dist/bin/cli.js" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "rolldown": "1.x", + "rollup": "2.x || 3.x || 4.x" + }, + "peerDependenciesMeta": { + "rolldown": { + "optional": true + }, + "rollup": { + "optional": true + } + } + }, + "node_modules/rollup-plugin-visualizer/node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/rollup-plugin-visualizer/node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/rollup-plugin-visualizer/node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/rollup-plugin-visualizer/node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/rollup-plugin-visualizer/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/rollup-plugin-visualizer/node_modules/source-map": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 12" + } + }, + "node_modules/run-applescript": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-async": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", + "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/sass": { + "version": "1.93.3", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.93.3.tgz", + "integrity": "sha512-elOcIZRTM76dvxNAjqYrucTSI0teAF/L2Lv0s6f6b7FOwcwIuA357bIE871580AjHJuSvLIRUosgV+lIWx6Rgg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "chokidar": "^4.0.0", + "immutable": "^5.0.2", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" + } + }, + "node_modules/sass-embedded": { + "version": "1.93.3", + "resolved": "https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.93.3.tgz", + "integrity": "sha512-+VUy01yfDqNmIVMd/LLKl2TTtY0ovZN0rTonh+FhKr65mFwIYgU9WzgIZKS7U9/SPCQvWTsTGx9jyt+qRm/XFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bufbuild/protobuf": "^2.5.0", + "buffer-builder": "^0.2.0", + "colorjs.io": "^0.5.0", + "immutable": "^5.0.2", + "rxjs": "^7.4.0", + "supports-color": "^8.1.1", + "sync-child-process": "^1.0.2", + "varint": "^6.0.0" + }, + "bin": { + "sass": "dist/bin/sass.js" + }, + "engines": { + "node": ">=16.0.0" + }, + "optionalDependencies": { + "sass-embedded-all-unknown": "1.93.3", + "sass-embedded-android-arm": "1.93.3", + "sass-embedded-android-arm64": "1.93.3", + "sass-embedded-android-riscv64": "1.93.3", + "sass-embedded-android-x64": "1.93.3", + "sass-embedded-darwin-arm64": "1.93.3", + "sass-embedded-darwin-x64": "1.93.3", + "sass-embedded-linux-arm": "1.93.3", + "sass-embedded-linux-arm64": "1.93.3", + "sass-embedded-linux-musl-arm": "1.93.3", + "sass-embedded-linux-musl-arm64": "1.93.3", + "sass-embedded-linux-musl-riscv64": "1.93.3", + "sass-embedded-linux-musl-x64": "1.93.3", + "sass-embedded-linux-riscv64": "1.93.3", + "sass-embedded-linux-x64": "1.93.3", + "sass-embedded-unknown-all": "1.93.3", + "sass-embedded-win32-arm64": "1.93.3", + "sass-embedded-win32-x64": "1.93.3" + } + }, + "node_modules/sass-embedded-all-unknown": { + "version": "1.93.3", + "resolved": "https://registry.npmjs.org/sass-embedded-all-unknown/-/sass-embedded-all-unknown-1.93.3.tgz", + "integrity": "sha512-3okGgnE41eg+CPLtAPletu6nQ4N0ij7AeW+Sl5Km4j29XcmqZQeFwYjHe1AlKTEgLi/UAONk1O8i8/lupeKMbw==", + "cpu": [ + "!arm", + "!arm64", + "!riscv64", + "!x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "sass": "1.93.3" + } + }, + "node_modules/sass-embedded-android-arm": { + "version": "1.93.3", + "resolved": "https://registry.npmjs.org/sass-embedded-android-arm/-/sass-embedded-android-arm-1.93.3.tgz", + "integrity": "sha512-8xOw9bywfOD6Wv24BgCmgjkk6tMrsOTTHcb28KDxeJtFtoxiUyMbxo0vChpPAfp2Hyg2tFFKS60s0s4JYk+Raw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-android-arm64": { + "version": "1.93.3", + "resolved": "https://registry.npmjs.org/sass-embedded-android-arm64/-/sass-embedded-android-arm64-1.93.3.tgz", + "integrity": "sha512-uqUl3Kt1IqdGVAcAdbmC+NwuUJy8tM+2ZnB7/zrt6WxWVShVCRdFnWR9LT8HJr7eJN7AU8kSXxaVX/gedanPsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-android-riscv64": { + "version": "1.93.3", + "resolved": "https://registry.npmjs.org/sass-embedded-android-riscv64/-/sass-embedded-android-riscv64-1.93.3.tgz", + "integrity": "sha512-2jNJDmo+3qLocjWqYbXiBDnfgwrUeZgZFHJIwAefU7Fn66Ot7rsXl+XPwlokaCbTpj7eMFIqsRAZ/uDueXNCJg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-android-x64": { + "version": "1.93.3", + "resolved": "https://registry.npmjs.org/sass-embedded-android-x64/-/sass-embedded-android-x64-1.93.3.tgz", + "integrity": "sha512-y0RoAU6ZenQFcjM9PjQd3cRqRTjqwSbtWLL/p68y2oFyh0QGN0+LQ826fc0ZvU/AbqCsAizkqjzOn6cRZJxTTQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-darwin-arm64": { + "version": "1.93.3", + "resolved": "https://registry.npmjs.org/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.93.3.tgz", + "integrity": "sha512-7zb/hpdMOdKteK17BOyyypemglVURd1Hdz6QGsggy60aUFfptTLQftLRg8r/xh1RbQAUKWFbYTNaM47J9yPxYg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-darwin-x64": { + "version": "1.93.3", + "resolved": "https://registry.npmjs.org/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.93.3.tgz", + "integrity": "sha512-Ek1Vp8ZDQEe327Lz0b7h3hjvWH3u9XjJiQzveq74RPpJQ2q6d9LfWpjiRRohM4qK6o4XOHw1X10OMWPXJtdtWg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-arm": { + "version": "1.93.3", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.93.3.tgz", + "integrity": "sha512-yeiv2y+dp8B4wNpd3+JsHYD0mvpXSfov7IGyQ1tMIR40qv+ROkRqYiqQvAOXf76Qwh4Y9OaYZtLpnsPjfeq6mA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-arm64": { + "version": "1.93.3", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.93.3.tgz", + "integrity": "sha512-RBrHWgfd8Dd8w4fbmdRVXRrhh8oBAPyeWDTKAWw8ZEmuXfVl4ytjDuyxaVilh6rR1xTRTNpbaA/YWApBlLrrNw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-musl-arm": { + "version": "1.93.3", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm/-/sass-embedded-linux-musl-arm-1.93.3.tgz", + "integrity": "sha512-fU0fwAwbp7sBE3h5DVU5UPzvaLg7a4yONfFWkkcCp6ZrOiPuGRHXXYriWQ0TUnWy4wE+svsVuWhwWgvlb/tkKg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-musl-arm64": { + "version": "1.93.3", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm64/-/sass-embedded-linux-musl-arm64-1.93.3.tgz", + "integrity": "sha512-PS829l+eUng+9W4PFclXGb4uA2+965NHV3/Sa5U7qTywjeeUUYTZg70dJHSqvhrBEfCc2XJABeW3adLJbyQYkw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-musl-riscv64": { + "version": "1.93.3", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-riscv64/-/sass-embedded-linux-musl-riscv64-1.93.3.tgz", + "integrity": "sha512-cK1oBY+FWQquaIGEeQ5H74KTO8cWsSWwXb/WaildOO9U6wmUypTgUYKQ0o5o/29nZbWWlM1PHuwVYTSnT23Jjg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-musl-x64": { + "version": "1.93.3", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-x64/-/sass-embedded-linux-musl-x64-1.93.3.tgz", + "integrity": "sha512-A7wkrsHu2/I4Zpa0NMuPGkWDVV7QGGytxGyUq3opSXgAexHo/vBPlGoDXoRlSdex0cV+aTMRPjoGIfdmNlHwyg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-riscv64": { + "version": "1.93.3", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-riscv64/-/sass-embedded-linux-riscv64-1.93.3.tgz", + "integrity": "sha512-vWkW1+HTF5qcaHa6hO80gx/QfB6GGjJUP0xLbnAoY4pwEnw5ulGv6RM8qYr8IDhWfVt/KH+lhJ2ZFxnJareisQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-x64": { + "version": "1.93.3", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.93.3.tgz", + "integrity": "sha512-k6uFxs+e5jSuk1Y0niCwuq42F9ZC5UEP7P+RIOurIm8w/5QFa0+YqeW+BPWEW5M1FqVOsNZH3qGn4ahqvAEjPA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-unknown-all": { + "version": "1.93.3", + "resolved": "https://registry.npmjs.org/sass-embedded-unknown-all/-/sass-embedded-unknown-all-1.93.3.tgz", + "integrity": "sha512-o5wj2rLpXH0C+GJKt/VpWp6AnMsCCbfFmnMAttcrsa+U3yrs/guhZ3x55KAqqUsE8F47e3frbsDL+1OuQM5DAA==", + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "!android", + "!darwin", + "!linux", + "!win32" + ], + "dependencies": { + "sass": "1.93.3" + } + }, + "node_modules/sass-embedded-win32-arm64": { + "version": "1.93.3", + "resolved": "https://registry.npmjs.org/sass-embedded-win32-arm64/-/sass-embedded-win32-arm64-1.93.3.tgz", + "integrity": "sha512-0dOfT9moy9YmBolodwYYXtLwNr4jL4HQC9rBfv6mVrD7ud8ue2kDbn+GVzj1hEJxvEexVSmDCf7MHUTLcGs9xQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-win32-x64": { + "version": "1.93.3", + "resolved": "https://registry.npmjs.org/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.93.3.tgz", + "integrity": "sha512-wHFVfxiS9hU/sNk7KReD+lJWRp3R0SLQEX4zfOnRP2zlvI2X4IQR5aZr9GNcuMP6TmNpX0nQPZTegS8+h9RrEg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/sass/node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/sass/node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/sax": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.1.4.tgz", + "integrity": "sha512-5f3k2PbGGp+YtKJjOItpg3P99IMD84E4HOvcfleTb5joCHNXYLsR9yWFPOYGgaeMPDubQILTCMdsFb2OMeOjtg==", + "dev": true, + "license": "ISC" + }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "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": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true, + "license": "ISC" + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "license": "MIT", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/stack-trace": { + "version": "1.0.0-pre2", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-1.0.0-pre2.tgz", + "integrity": "sha512-2ztBJRek8IVofG9DBJqdy2N5kulaacX30Nz7xmkYF6ale9WBVmIy6mFBchvGX7Vx/MyjBhx+Rcxqrj+dbOnQ6A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/streamx": { + "version": "2.23.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.23.0.tgz", + "integrity": "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "events-universal": "^1.0.0", + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sync-child-process": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/sync-child-process/-/sync-child-process-1.0.2.tgz", + "integrity": "sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "sync-message-port": "^1.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/sync-message-port": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sync-message-port/-/sync-message-port-1.1.3.tgz", + "integrity": "sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/synckit": { + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", + "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.2.9" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" + } + }, + "node_modules/tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, + "node_modules/terser": { + "version": "5.44.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.1.tgz", + "integrity": "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.15.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/text-decoder": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", + "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.6.4" + } + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyglobby": { + "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.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "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" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/ts-essentials": { + "version": "9.4.2", + "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-9.4.2.tgz", + "integrity": "sha512-mB/cDhOvD7pg3YCLk2rOtejHjjdSi9in/IBYE13S+8WA5FBSraYf4V/ws55uvs0IvQ/l0wBOlXy5yBNZ9Bl8ZQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "typescript": ">=4.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "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.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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/ufo": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", + "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "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", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/varint": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", + "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", + "dev": true, + "license": "MIT" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vite": { + "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", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite-plugin-checker": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/vite-plugin-checker/-/vite-plugin-checker-0.11.0.tgz", + "integrity": "sha512-iUdO9Pl9UIBRPAragwi3as/BXXTtRu4G12L3CMrjx+WVTd9g/MsqNakreib9M/2YRVkhZYiTEwdH2j4Dm0w7lw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "chokidar": "^4.0.3", + "npm-run-path": "^6.0.0", + "picocolors": "^1.1.1", + "picomatch": "^4.0.3", + "tiny-invariant": "^1.3.3", + "tinyglobby": "^0.2.14", + "vscode-uri": "^3.1.0" + }, + "engines": { + "node": ">=16.11" + }, + "peerDependencies": { + "@biomejs/biome": ">=1.7", + "eslint": ">=7", + "meow": "^13.2.0", + "optionator": "^0.9.4", + "oxlint": ">=1", + "stylelint": ">=16", + "typescript": "*", + "vite": ">=5.4.20", + "vls": "*", + "vti": "*", + "vue-tsc": "~2.2.10 || ^3.0.0" + }, + "peerDependenciesMeta": { + "@biomejs/biome": { + "optional": true + }, + "eslint": { + "optional": true + }, + "meow": { + "optional": true + }, + "optionator": { + "optional": true + }, + "oxlint": { + "optional": true + }, + "stylelint": { + "optional": true + }, + "typescript": { + "optional": true + }, + "vls": { + "optional": true + }, + "vti": { + "optional": true + }, + "vue-tsc": { + "optional": true + } + } + }, + "node_modules/vite-plugin-checker/node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/vite-plugin-checker/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vite-plugin-checker/node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/vite/node_modules/fdir": { + "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" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vscode-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/vue": { + "version": "3.5.24", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.24.tgz", + "integrity": "sha512-uTHDOpVQTMjcGgrqFPSb8iO2m1DUvo+WbGqoXQz8Y1CeBYQ0FXf2z1gLRaBtHjlRz7zZUBHxjVB5VTLzYkvftg==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.24", + "@vue/compiler-sfc": "3.5.24", + "@vue/runtime-dom": "3.5.24", + "@vue/server-renderer": "3.5.24", + "@vue/shared": "3.5.24" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-eslint-parser": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-10.2.0.tgz", + "integrity": "sha512-CydUvFOQKD928UzZhTp4pr2vWz1L+H99t7Pkln2QSPdvmURT0MoC4wUccfCnuEaihNsu9aYYyk+bep8rlfkUXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.6.0", + "semver": "^7.6.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + } + }, + "node_modules/vue-eslint-parser/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/vue-router": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.6.3.tgz", + "integrity": "sha512-ARBedLm9YlbvQomnmq91Os7ck6efydTSpRP3nuOKCvgJOHNrhRoJDSKtee8kcL1Vf7nz6U+PMBL+hTvR3bTVQg==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.4" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, + "node_modules/vue-tsc": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-3.1.3.tgz", + "integrity": "sha512-StMNfZHwPIXQgY3KxPKM0Jsoc8b46mDV3Fn2UlHCBIwRJApjqrSwqeMYgWf0zpN+g857y74pv7GWuBm+UqQe1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/typescript": "2.4.23", + "@vue/language-core": "3.1.3" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "license": "MIT", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/webpack-merge": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", + "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wsl-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", + "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yoctocolors-cjs": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz", + "integrity": "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zip-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-6.0.1.tgz", + "integrity": "sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "archiver-utils": "^5.0.0", + "compress-commons": "^6.0.2", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + } + } +} diff --git a/packages/auth_service/auth-frontend/package.json b/packages/auth_service/auth-frontend/package.json new file mode 100644 index 0000000000..439c80191c --- /dev/null +++ b/packages/auth_service/auth-frontend/package.json @@ -0,0 +1,45 @@ +{ + "name": "openwb-auth-frontend", + "version": "0.0.1", + "description": "Authentication frontend for openWB", + "productName": "openWB Auth Frontend", + "author": "Lutz Bender ", + "type": "module", + "private": true, + "scripts": { + "lint": "eslint -c ./eslint.config.js \"./src*/**/*.{ts,js,cjs,mjs,vue}\"", + "format": "prettier --write \"**/*.{js,ts,vue,scss,html,md,json}\" --ignore-path .gitignore", + "test": "echo \"No test specified\" && exit 0", + "dev": "quasar dev", + "build": "quasar build", + "postinstall": "quasar prepare" + }, + "dependencies": { + "axios": "^1.2.1", + "@quasar/extras": "^1.16.4", + "quasar": "^2.16.0", + "vue": "^3.5.22", + "vue-router": "^4.0.12" + }, + "devDependencies": { + "@eslint/js": "^9.14.0", + "eslint": "^9.14.0", + "eslint-plugin-vue": "^10.4.0", + "globals": "^16.4.0", + "vue-tsc": "^3.0.7", + "@vue/eslint-config-typescript": "^14.4.0", + "vite-plugin-checker": "^0.11.0", + "vue-eslint-parser": "^10.2.0", + "@vue/eslint-config-prettier": "^10.1.0", + "prettier": "^3.3.3", + "@types/node": "^20.5.9", + "@quasar/app-vite": "^2.1.0", + "autoprefixer": "^10.4.2", + "typescript": "^5.9.2" + }, + "engines": { + "node": "^28 || ^26 || ^24 || ^22 || ^20", + "npm": ">= 6.13.4", + "yarn": ">= 1.21.1" + } +} diff --git a/packages/auth_service/auth-frontend/postcss.config.js b/packages/auth_service/auth-frontend/postcss.config.js new file mode 100644 index 0000000000..4498380fc7 --- /dev/null +++ b/packages/auth_service/auth-frontend/postcss.config.js @@ -0,0 +1,29 @@ +// https://github.com/michael-ciniawsky/postcss-load-config + +import autoprefixer from 'autoprefixer'; +// import rtlcss from 'postcss-rtlcss' + +export default { + plugins: [ + // https://github.com/postcss/autoprefixer + autoprefixer({ + overrideBrowserslist: [ + 'last 4 Chrome versions', + 'last 4 Firefox versions', + 'last 4 Edge versions', + 'last 4 Safari versions', + 'last 4 Android versions', + 'last 4 ChromeAndroid versions', + 'last 4 FirefoxAndroid versions', + 'last 4 iOS versions', + ], + }), + + // https://github.com/elchininet/postcss-rtlcss + // If you want to support RTL css, then + // 1. yarn/pnpm/bun/npm install postcss-rtlcss + // 2. optionally set quasar.config.js > framework > lang to an RTL language + // 3. uncomment the following line (and its import statement above): + // rtlcss() + ], +}; diff --git a/packages/auth_service/auth-frontend/public/favicon.ico b/packages/auth_service/auth-frontend/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..ae7bbdb712f8ce9fe49761b68ef3a2d4c51606f9 GIT binary patch literal 64483 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 literal 0 HcmV?d00001 diff --git a/packages/auth_service/auth-frontend/public/icons/favicon-128x128.png b/packages/auth_service/auth-frontend/public/icons/favicon-128x128.png new file mode 100644 index 0000000000000000000000000000000000000000..14011761929f4ffbef81be318a347c0032eb6f42 GIT binary patch literal 12324 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 h$J#u>{O`^5_ { + return { + // https://v2.quasar.dev/quasar-cli-vite/prefetch-feature + // preFetch: true, + + // app boot file (/src/boot) + // --> boot files are part of "main.js" + // https://v2.quasar.dev/quasar-cli-vite/boot-files + boot: ['axios'], + + // https://v2.quasar.dev/quasar-cli-vite/quasar-config-file#css + css: ['app.scss'], + + // https://github.com/quasarframework/quasar/tree/dev/extras + extras: [ + // 'ionicons-v4', + // 'mdi-v7', + // 'fontawesome-v6', + // 'eva-icons', + // 'themify', + // 'line-awesome', + // 'roboto-font-latin-ext', // this or either 'roboto-font', NEVER both! + + 'roboto-font', // optional, you are not bound to it + 'material-icons', // optional, you are not bound to it + ], + + // Full list of options: https://v2.quasar.dev/quasar-cli-vite/quasar-config-file#build + build: { + target: { + browser: ['es2022', 'firefox115', 'chrome115', 'safari14'], + node: 'node20', + }, + + typescript: { + strict: true, + vueShim: true, + // extendTsConfig (tsConfig) {} + }, + + vueRouterMode: 'history', // available values: 'hash', 'history' + // vueRouterBase, + // vueDevtools, + // vueOptionsAPI: false, + + // rebuildCache: true, // rebuilds Vite/linter/etc cache on startup + + // publicPath: '/', + // analyze: true, + // env: {}, + // rawDefine: {} + // ignorePublicFolder: true, + // minify: false, + // polyfillModulePreload: true, + // distDir + + // extendViteConf (viteConf) {}, + // viteVuePluginOptions: {}, + + vitePlugins: [ + [ + 'vite-plugin-checker', + { + vueTsc: true, + eslint: { + lintCommand: 'eslint -c ./eslint.config.js "./src*/**/*.{ts,js,mjs,cjs,vue}"', + useFlatConfig: true, + }, + }, + { server: false }, + ], + ], + }, + + // Full list of options: https://v2.quasar.dev/quasar-cli-vite/quasar-config-file#devserver + devServer: { + // https: true, + open: true, // opens browser window automatically + }, + + // https://v2.quasar.dev/quasar-cli-vite/quasar-config-file#framework + framework: { + config: {}, + + iconSet: 'material-icons', // Quasar icon set + lang: 'de-DE', // Quasar language pack + + // For special cases outside of where the auto-import strategy can have an impact + // (like functional components as one of the examples), + // you can manually specify Quasar components/directives to be available everywhere: + // + // components: [], + // directives: [], + + // Quasar plugins + plugins: [], + }, + + // animations: 'all', // --- includes all animations + // https://v2.quasar.dev/options/animations + animations: [], + + // https://v2.quasar.dev/quasar-cli-vite/quasar-config-file#sourcefiles + // sourceFiles: { + // rootComponent: 'src/App.vue', + // router: 'src/router/index', + // store: 'src/store/index', + // pwaRegisterServiceWorker: 'src-pwa/register-service-worker', + // pwaServiceWorker: 'src-pwa/custom-service-worker', + // pwaManifestFile: 'src-pwa/manifest.json', + // electronMain: 'src-electron/electron-main', + // electronPreload: 'src-electron/electron-preload' + // bexManifestFile: 'src-bex/manifest.json + // }, + + // https://v2.quasar.dev/quasar-cli-vite/developing-ssr/configuring-ssr + ssr: { + prodPort: 3000, // The default port that the production server should use + // (gets superseded if process.env.PORT is specified at runtime) + + middlewares: [ + 'render', // keep this as last one + ], + + // extendPackageJson (json) {}, + // extendSSRWebserverConf (esbuildConf) {}, + + // manualStoreSerialization: true, + // manualStoreSsrContextInjection: true, + // manualStoreHydration: true, + // manualPostHydrationTrigger: true, + + pwa: false, + // pwaOfflineHtmlFilename: 'offline.html', // do NOT use index.html as name! + + // pwaExtendGenerateSWOptions (cfg) {}, + // pwaExtendInjectManifestOptions (cfg) {} + }, + + // https://v2.quasar.dev/quasar-cli-vite/developing-pwa/configuring-pwa + pwa: { + workboxMode: 'GenerateSW', // 'GenerateSW' or 'InjectManifest' + // swFilename: 'sw.js', + // manifestFilename: 'manifest.json', + // extendManifestJson (json) {}, + // useCredentialsForManifestTag: true, + // injectPwaMetaTags: false, + // extendPWACustomSWConf (esbuildConf) {}, + // extendGenerateSWOptions (cfg) {}, + // extendInjectManifestOptions (cfg) {} + }, + + // Full list of options: https://v2.quasar.dev/quasar-cli-vite/developing-cordova-apps/configuring-cordova + cordova: { + // noIosLegacyBuildFlag: true, // uncomment only if you know what you are doing + }, + + // Full list of options: https://v2.quasar.dev/quasar-cli-vite/developing-capacitor-apps/configuring-capacitor + capacitor: { + hideSplashscreen: true, + }, + + // Full list of options: https://v2.quasar.dev/quasar-cli-vite/developing-electron-apps/configuring-electron + electron: { + // extendElectronMainConf (esbuildConf) {}, + // extendElectronPreloadConf (esbuildConf) {}, + + // extendPackageJson (json) {}, + + // Electron preload scripts (if any) from /src-electron, WITHOUT file extension + preloadScripts: ['electron-preload'], + + // specify the debugging port to use for the Electron app when running in development mode + inspectPort: 5858, + + bundler: 'packager', // 'packager' or 'builder' + + packager: { + // https://github.com/electron-userland/electron-packager/blob/master/docs/api.md#options + // OS X / Mac App Store + // appBundleId: '', + // appCategoryType: '', + // osxSign: '', + // protocol: 'myapp://path', + // Windows only + // win32metadata: { ... } + }, + + builder: { + // https://www.electron.build/configuration/configuration + + appId: 'openwb-auth-frontend', + }, + }, + + // Full list of options: https://v2.quasar.dev/quasar-cli-vite/developing-browser-extensions/configuring-bex + bex: { + // extendBexScriptsConf (esbuildConf) {}, + // extendBexManifestJson (json) {}, + + /** + * The list of extra scripts (js/ts) not in your bex manifest that you want to + * compile and use in your browser extension. Maybe dynamic use them? + * + * Each entry in the list should be a relative filename to /src-bex/ + * + * @example [ 'my-script.ts', 'sub-folder/my-other-script.js' ] + */ + extraScripts: [], + }, + }; +}); diff --git a/packages/auth_service/auth-frontend/src/App.vue b/packages/auth_service/auth-frontend/src/App.vue new file mode 100644 index 0000000000..9d87945ab4 --- /dev/null +++ b/packages/auth_service/auth-frontend/src/App.vue @@ -0,0 +1,7 @@ + + + diff --git a/packages/auth_service/auth-frontend/src/assets/quasar-logo-vertical.svg b/packages/auth_service/auth-frontend/src/assets/quasar-logo-vertical.svg new file mode 100644 index 0000000000..821083104a --- /dev/null +++ b/packages/auth_service/auth-frontend/src/assets/quasar-logo-vertical.svg @@ -0,0 +1,15 @@ + + + + + + + + + \ No newline at end of file diff --git a/packages/auth_service/auth-frontend/src/boot/.gitkeep b/packages/auth_service/auth-frontend/src/boot/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/auth_service/auth-frontend/src/boot/axios.ts b/packages/auth_service/auth-frontend/src/boot/axios.ts new file mode 100644 index 0000000000..fe961f51c3 --- /dev/null +++ b/packages/auth_service/auth-frontend/src/boot/axios.ts @@ -0,0 +1,34 @@ +import { defineBoot } from '#q-app/wrappers'; +import axios, { type AxiosInstance } from 'axios'; + +declare module 'vue' { + interface ComponentCustomProperties { + $axios: AxiosInstance; + $api: AxiosInstance; + } +} + +// Be careful when using SSR for cross-request state pollution +// due to creating a Singleton instance here; +// If any client changes this (global) instance, it might be a +// good idea to move this instance creation inside of the +// "export default () => {}" function below (which runs individually +// for each client) +const api = axios.create({ + baseURL: '/auth', + withCredentials: true, +}); + +export default defineBoot(({ app }) => { + // for use inside Vue files (Options API) through this.$axios and this.$api + + app.config.globalProperties.$axios = axios; + // ^ ^ ^ this will allow you to use this.$axios (for Vue Options API form) + // so you won't necessarily have to import axios in each vue file + + app.config.globalProperties.$api = api; + // ^ ^ ^ this will allow you to use this.$api (for Vue Options API form) + // so you can easily perform requests against your app's API +}); + +export { axios, api }; diff --git a/packages/auth_service/auth-frontend/src/components/EssentialLink.vue b/packages/auth_service/auth-frontend/src/components/EssentialLink.vue new file mode 100644 index 0000000000..4b5a173963 --- /dev/null +++ b/packages/auth_service/auth-frontend/src/components/EssentialLink.vue @@ -0,0 +1,27 @@ + + + diff --git a/packages/auth_service/auth-frontend/src/components/models.ts b/packages/auth_service/auth-frontend/src/components/models.ts new file mode 100644 index 0000000000..69459204b1 --- /dev/null +++ b/packages/auth_service/auth-frontend/src/components/models.ts @@ -0,0 +1,8 @@ +export interface Todo { + id: number; + content: string; +} + +export interface Meta { + totalCount: number; +} diff --git a/packages/auth_service/auth-frontend/src/css/app.scss b/packages/auth_service/auth-frontend/src/css/app.scss new file mode 100644 index 0000000000..ecac98f346 --- /dev/null +++ b/packages/auth_service/auth-frontend/src/css/app.scss @@ -0,0 +1 @@ +// app global css in SCSS form diff --git a/packages/auth_service/auth-frontend/src/css/quasar.variables.scss b/packages/auth_service/auth-frontend/src/css/quasar.variables.scss new file mode 100644 index 0000000000..2605a0df98 --- /dev/null +++ b/packages/auth_service/auth-frontend/src/css/quasar.variables.scss @@ -0,0 +1,25 @@ +// Quasar SCSS (& Sass) Variables +// -------------------------------------------------- +// To customize the look and feel of this app, you can override +// the Sass/SCSS variables found in Quasar's source Sass/SCSS files. + +// Check documentation for full list of Quasar variables + +// Your own variables (that are declared here) and Quasar's own +// ones will be available out of the box in your .vue/.scss/.sass files + +// It's highly recommended to change the default colors +// to match your app's branding. +// Tip: Use the "Theme Builder" on Quasar's documentation website. + +$primary: #1976d2; +$secondary: #26a69a; +$accent: #9c27b0; + +$dark: #1d1d1d; +$dark-page: #121212; + +$positive: #21ba45; +$negative: #c10015; +$info: #31ccec; +$warning: #f2c037; diff --git a/packages/auth_service/auth-frontend/src/env.d.ts b/packages/auth_service/auth-frontend/src/env.d.ts new file mode 100644 index 0000000000..12dcd189fe --- /dev/null +++ b/packages/auth_service/auth-frontend/src/env.d.ts @@ -0,0 +1,7 @@ +declare namespace NodeJS { + interface ProcessEnv { + NODE_ENV: string; + VUE_ROUTER_MODE: 'hash' | 'history' | 'abstract' | undefined; + VUE_ROUTER_BASE: string | undefined; + } +} diff --git a/packages/auth_service/auth-frontend/src/layouts/MainLayout.vue b/packages/auth_service/auth-frontend/src/layouts/MainLayout.vue new file mode 100644 index 0000000000..b89696ce2b --- /dev/null +++ b/packages/auth_service/auth-frontend/src/layouts/MainLayout.vue @@ -0,0 +1,106 @@ + + + diff --git a/packages/auth_service/auth-frontend/src/pages/ErrorNotFound.vue b/packages/auth_service/auth-frontend/src/pages/ErrorNotFound.vue new file mode 100644 index 0000000000..eb5ff5304f --- /dev/null +++ b/packages/auth_service/auth-frontend/src/pages/ErrorNotFound.vue @@ -0,0 +1,23 @@ + + + diff --git a/packages/auth_service/auth-frontend/src/pages/IndexPage.vue b/packages/auth_service/auth-frontend/src/pages/IndexPage.vue new file mode 100644 index 0000000000..de1adafabc --- /dev/null +++ b/packages/auth_service/auth-frontend/src/pages/IndexPage.vue @@ -0,0 +1,8 @@ + + + diff --git a/packages/auth_service/auth-frontend/src/pages/LoginPage.vue b/packages/auth_service/auth-frontend/src/pages/LoginPage.vue new file mode 100644 index 0000000000..f6aac69223 --- /dev/null +++ b/packages/auth_service/auth-frontend/src/pages/LoginPage.vue @@ -0,0 +1,64 @@ + + + diff --git a/packages/auth_service/auth-frontend/src/pages/LogoutPage.vue b/packages/auth_service/auth-frontend/src/pages/LogoutPage.vue new file mode 100644 index 0000000000..c1a376d974 --- /dev/null +++ b/packages/auth_service/auth-frontend/src/pages/LogoutPage.vue @@ -0,0 +1,38 @@ + + + diff --git a/packages/auth_service/auth-frontend/src/router/index.ts b/packages/auth_service/auth-frontend/src/router/index.ts new file mode 100644 index 0000000000..ea3c763d88 --- /dev/null +++ b/packages/auth_service/auth-frontend/src/router/index.ts @@ -0,0 +1,37 @@ +import { defineRouter } from '#q-app/wrappers'; +import { + createMemoryHistory, + createRouter, + createWebHashHistory, + createWebHistory, +} from 'vue-router'; +import routes from './routes'; + +/* + * If not building with SSR mode, you can + * directly export the Router instantiation; + * + * The function below can be async too; either use + * async/await or return a Promise which resolves + * with the Router instance. + */ + +export default defineRouter(function (/* { store, ssrContext } */) { + const createHistory = process.env.SERVER + ? createMemoryHistory + : process.env.VUE_ROUTER_MODE === 'history' + ? createWebHistory + : createWebHashHistory; + + const Router = createRouter({ + scrollBehavior: () => ({ left: 0, top: 0 }), + routes, + + // Leave this as is and make changes in quasar.conf.js instead! + // quasar.conf.js -> build -> vueRouterMode + // quasar.conf.js -> build -> publicPath + history: createHistory(process.env.VUE_ROUTER_BASE), + }); + + return Router; +}); diff --git a/packages/auth_service/auth-frontend/src/router/routes.ts b/packages/auth_service/auth-frontend/src/router/routes.ts new file mode 100644 index 0000000000..23073aa5b5 --- /dev/null +++ b/packages/auth_service/auth-frontend/src/router/routes.ts @@ -0,0 +1,22 @@ +import type { RouteRecordRaw } from 'vue-router'; + +const routes: RouteRecordRaw[] = [ + { + path: '/', + component: () => import('layouts/MainLayout.vue'), + children: [ + { path: '', component: () => import('pages/IndexPage.vue') }, + { path: '/login', component: () => import('pages/LoginPage.vue') }, + { path: '/logout', component: () => import('pages/LogoutPage.vue') }, + ], + }, + + // Always leave this as last one, + // but you can also remove it + { + path: '/:catchAll(.*)*', + component: () => import('pages/ErrorNotFound.vue'), + }, +]; + +export default routes; diff --git a/packages/auth_service/auth-frontend/tsconfig.json b/packages/auth_service/auth-frontend/tsconfig.json new file mode 100644 index 0000000000..3c0b1902c9 --- /dev/null +++ b/packages/auth_service/auth-frontend/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "./.quasar/tsconfig.json" +} diff --git a/packages/auth_service/auth_server.py b/packages/auth_service/auth_server.py new file mode 100644 index 0000000000..7955e8759f --- /dev/null +++ b/packages/auth_service/auth_server.py @@ -0,0 +1,387 @@ +#!/usr/bin/env python3 +# auth_server.py — Flask Auth-Service mit JWT, Refresh-Rotation, DynSec-Integration, SQlite +# Python 3.11 + +from typing import Optional +from flask import Flask, request, jsonify, make_response +import os +import sqlite3 +from passlib.hash import bcrypt +# import secrets +# import requests +# import time + +# ---------------------- +# Konfiguration via ENV +# ---------------------- +DB_PATH = os.environ.get("AUTH_DB", "./auth.db") +MOSQUITTO_API = os.environ.get("MOSQUITTO_API", "http://localhost:8080/dynamic-security/v1") +MOSQ_ADMIN_USER = os.environ.get("MOSQ_ADMIN_USER", "admin") +MOSQ_ADMIN_PASS = os.environ.get("MOSQ_ADMIN_PASS", "changeme") +MOSQ_ROLE = os.environ.get("MOSQ_ROLE", "user") +TLS_ONLY = os.environ.get("TLS_ONLY", "1") == "1" # wenn True cookies mit Secure setzen +COOKIE_NAME = "mqtt_auth" + +# ---------------------- +# Flask App +# ---------------------- +app = Flask(__name__) + + +# ---------------------- +# DB Hilfsfunktionen +# ---------------------- +def db_connect(): + db_connection = sqlite3.connect(DB_PATH, detect_types=sqlite3.PARSE_DECLTYPES) + db_connection.row_factory = sqlite3.Row + return db_connection + + +# ---------------------- +# Nutzer-Logik +# ---------------------- +def get_user(email): + db_connection = db_connect() + cur = db_connection.execute( + "SELECT email, password_hash, first_name, last_name, role, disabled, comment FROM users WHERE email = ?", + (email,) + ) + row = cur.fetchone() + db_connection.close() + return row + + +def verify_user_password(email, password): + row = get_user(email) + if not row or row["disabled"]: + return False + try: + return bcrypt.verify(password, row["password_hash"]) + except Exception: + return False + + +def verify_user_role(email, role="admin"): + row = get_user(email) + if row and not row["disabled"] and row["role"] == role: + return True + return False + + +# ---------------------- +# Auth-Hilfsfunktion +# ---------------------- +def get_authenticated_email(required_role: Optional[str] = None): + """ + Prüft das Auth-Cookie und optional die Rolle. + Rückgabe: (email, None) bei Erfolg oder (None, (jsonify..., status)) bei Fehler. + """ + auth_data = request.cookies.get(COOKIE_NAME) + email, password = (auth_data or ":").split(":", 1) + if not verify_user_password(email, password): + return None, (jsonify(error="Not Authenticated"), 401) + if required_role and not verify_user_role(email, role=required_role): + return None, (jsonify(error="Forbidden"), 403) + return email, None + + +# ---------------------- +# Mosquitto Dynamic Security helpers +# ---------------------- +# def create_temp_mqtt_user(username_hint: str, ttl_seconds: int = 3600) -> dict: +# """ +# Legt einen temporären Mosquitto-Client (User) an via Dynamic Security API. +# Rückgabe: { "tempUser": "...", "tempPass": "...", "expires_at": epoch_sec } +# """ +# temp_user = f"sess_{secrets.token_hex(6)}" +# temp_pass = secrets.token_urlsafe(12) +# payload = { +# "username": temp_user, +# "password": temp_pass, +# "roles": [MOSQ_ROLE] +# } +# url = f"{MOSQUITTO_API}/client" +# try: +# r = requests.post(url, auth=(MOSQ_ADMIN_USER, MOSQ_ADMIN_PASS), json=payload, timeout=5) +# except Exception as e: +# raise RuntimeError(f"Mosquitto API nicht erreichbar: {e}") +# if r.status_code not in (200, 201): +# raise RuntimeError(f"Mosquitto-API Fehler ({r.status_code}): {r.text}") +# expires_at = int(time.time()) + ttl_seconds +# return {"tempUser": temp_user, "tempPass": temp_pass, "expires_at": expires_at} + + +# def delete_mqtt_user(username: str): +# url = f"{MOSQUITTO_API}/client/{username}" +# try: +# r = requests.delete(url, auth=(MOSQ_ADMIN_USER, MOSQ_ADMIN_PASS), timeout=5) +# return r.status_code in (200, 204) +# except Exception: +# return False + + +# ---------------------- +# Routes: Auth-Plugin kompatible Endpoints +# ---------------------- +# @app.post("/auth") +# def auth_check(): +# """ +# Erwartet form-encoded oder JSON: +# - username +# - password +# Antwort: +# - 200 OK -> erlaubt +# - 401/403 -> abgelehnt +# """ +# data = request.form.to_dict() or request.get_json(silent=True) or {} +# email = data.get("username", "") +# password = data.get("password", "") + +# # klassische Nutzer/Passwort-Prüfung +# if verify_user_password(email, password): +# return ("OK", 200) + +# return ("Unauthorized", 401) + + +# @app.post("/acl") +# def acl_check(): +# """ +# Erwartet (form oder json): +# - username +# - topic +# - acc (1=sub, 2=pub; je nach Plugin) +# - clientid (optional) +# Antwort: +# - 200 OK -> erlaubt +# - 403 -> verweigert +# """ +# data = request.form.to_dict() or request.get_json(silent=True) or {} +# email = data.get("username", "") +# topic = data.get("topic", "") +# acc = int(data.get("acc", 0)) + +# row = get_user(email) +# if not row or row["disabled"]: +# return ("Forbidden", 403) + +# role = row["role"] +# # Beispiel-ACLs — bitte an deine Anforderungen anpassen: +# if role == "admin": +# return ("OK", 200) +# if role == "viewer" and acc == 1: +# # nur lesen, zusätzlich Topic-Filter möglich +# if topic.startswith("sensors/") or topic.startswith("status/"): +# return ("OK", 200) +# if role == "operator": +# # operator darf lesen und schreiben auf device-Tops +# if topic.startswith("devices/") or topic.startswith("commands/"): +# return ("OK", 200) +# # Standard: verweigern +# return ("Forbidden", 403) + + +# ---------------------- +# Web API Endpoints (Login / Refresh / MQTT credentials / Logout / Health) +# ---------------------- +def set_cookie(resp, name, value, expires=None): + resp.set_cookie( + name, + value, + httponly=False, + secure=TLS_ONLY, + samesite="Strict", + expires=expires + ) + + +@app.post("/api/login") +def web_login(): + data: dict = request.get_json(force=True) + email: Optional[str] = data.get("email") + password: Optional[str] = data.get("password") + if email is None or password is None: + return jsonify(error="email/password required"), 400 + if not verify_user_password(email, password): + return jsonify(error="invalid credentials"), 401 + + resp = make_response(jsonify(success=True)) + # Cookie setzen + set_cookie(resp, COOKIE_NAME, f"{email}:{password}", expires=None) + return resp + + +@app.post("/api/logout") +def logout(): + resp = make_response(jsonify(success=True)) + # Cookie löschen + set_cookie(resp, COOKIE_NAME, "", expires=0) + return resp + + +@app.get("/api/health") +def health(): + return jsonify(status="ok") + + +# ---------------------- +# Admin Endpoints +# ---------------------- + + +# ---------------------- +# User-Create Endpoint +# ---------------------- +@app.post("/admin/create_user") +def admin_create_user(): + # Auth prüfen + _, err = get_authenticated_email(required_role="admin") + if err: + return err + data = request.get_json(force=True) + email = data.get("email") + password = data.get("password") + first_name = data.get("first_name") + last_name = data.get("last_name") + role = data.get("role", "viewer") + comment = data.get("comment") + if not email or not password: + return jsonify(error="email and password required"), 400 + pw_hash = bcrypt.hash(password) + conn = db_connect() + try: + conn.execute( + "INSERT INTO users (email, password_hash, first_name, last_name, role, disabled, comment) " + "VALUES (?, ?, ?, ?, ?, 0, ?)", + (email, pw_hash, first_name, last_name, role, comment) + ) + conn.commit() + except sqlite3.IntegrityError: + return jsonify(error=f"user with email '{email}' already exists"), 409 + finally: + conn.close() + return jsonify(success=True, email=email) + + +# ---------------------- +# User-Update Endpoint +# ---------------------- +@app.post("/admin/update_user") +def admin_update_user(): + # Auth prüfen + _, err = get_authenticated_email(required_role="admin") + if err: + return err + data = request.get_json(force=True) + email = data.get("email") + first_name = data.get("first_name") + last_name = data.get("last_name") + role = data.get("role", "viewer") + disabled = data.get("disabled", 0) + comment = data.get("comment") + if not email: + return jsonify(error="email required"), 400 + conn = db_connect() + try: + conn.execute( + "UPDATE users SET first_name = ?, last_name = ?, role = ?, disabled = ?, comment = ? " + "WHERE email = ?", + (first_name, last_name, role, disabled, comment, email) + ) + conn.commit() + except sqlite3.IntegrityError: + return jsonify(error=f"user with email '{email}' already exists"), 409 + finally: + conn.close() + return jsonify(success=True, email=email) + + +# ---------------------- +# User-Delete Endpoint +# ---------------------- +@app.post("/admin/delete_user") +def admin_delete_user(): + # Auth prüfen + _, err = get_authenticated_email(required_role="admin") + if err: + return err + data = request.get_json(force=True) + email = data.get("email") + if not email: + return jsonify(error="email required"), 400 + conn = db_connect() + cur = conn.execute( + "DELETE FROM users WHERE email = ?", + (email,) + ) + deleted = cur.rowcount + conn.commit() + conn.close() + if deleted == 0: + return jsonify(error="user not found"), 404 + return jsonify(success=True, email=email) + + +# ---------------------- +# User-Password Endpoint +# ---------------------- +@app.post("/admin/update_password") +def admin_update_password(): + # Auth prüfen + _, err = get_authenticated_email(required_role="admin") + if err: + return err + data = request.get_json(force=True) + email = data.get("email") + password = data.get("password") + if not email or not password: + return jsonify(error="email and password required"), 400 + pw_hash = bcrypt.hash(password) + conn = db_connect() + cur = conn.execute( + "UPDATE users SET password_hash = ? " + "WHERE email = ?", + (pw_hash, email) + ) + modified = cur.rowcount + conn.commit() + conn.close() + if modified == 0: + return jsonify(error=f"user with email '{email}' not found"), 409 + return jsonify(success=True, email=email) + + +# ---------------------- +# Get-Users Endpoint +# ---------------------- +@app.get("/admin/get_users") +def admin_get_users(): + # Auth prüfen + email, err = get_authenticated_email(required_role="admin") + if err: + return err + conn = db_connect() + cur = conn.execute("SELECT email, first_name, last_name, comment, role, disabled, created_at FROM users") + users = [dict(row) for row in cur.fetchall()] + conn.close() + return jsonify(users=users, requested_by=email) + + +# ---------------------- +# Start App +# ---------------------- +if __name__ == "__main__": + # Hinweis: Für Prod: WSGI-Server wie gunicorn + HTTPS-Frontend (z. B. nginx) verwenden + host = os.environ.get("LISTEN_HOST", "127.0.0.1") + port = int(os.environ.get("LISTEN_PORT", "3000")) + debug = os.environ.get("AUTH_DEBUG", "0") == "1" + # Starte mit waitress, falls verfügbar; sonst Fallback auf Flask-Dev-Server + try: + from waitress import serve + if debug: + import logging + logger = logging.getLogger('waitress') + logger.setLevel(logging.INFO) + serve(app, host=host, port=port) + except Exception: + app.run(host=host, port=port, debug=debug) diff --git a/packages/auth_service/init_db.py b/packages/auth_service/init_db.py new file mode 100644 index 0000000000..6506188516 --- /dev/null +++ b/packages/auth_service/init_db.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +# init_db.py +import sqlite3 +from passlib.hash import bcrypt +import os +import getpass + +DB_PATH = os.environ.get("AUTH_DB", "./auth.db") + + +def init_db(): + db_connection = sqlite3.connect(DB_PATH) + db_cursor = db_connection.cursor() + db_cursor.executescript(""" + CREATE TABLE IF NOT EXISTS users ( + email TEXT PRIMARY KEY, + password_hash TEXT NOT NULL, + first_name TEXT, + last_name TEXT, + role TEXT NOT NULL DEFAULT 'viewer', + disabled INTEGER NOT NULL DEFAULT 0, + comment TEXT, + password_token TEXT, + password_token_expires_at TIMESTAMP, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ); + """) + db_connection.commit() + db_connection.close() + print("DB initialisiert:", DB_PATH) + + +def create_user(email, password, first_name=None, last_name=None, role="viewer", comment=None): + db_connection = sqlite3.connect(DB_PATH) + db_cursor = db_connection.cursor() + pw_hash = bcrypt.hash(password) + db_cursor.execute( + "INSERT OR REPLACE INTO users (email, password_hash, first_name, last_name, role, disabled, comment) " + "VALUES (?, ?, ?, ?, ?, 0, ?);", + (email, pw_hash, first_name, last_name, role, comment) + ) + db_connection.commit() + db_connection.close() + print(f"Benutzer '{username}' angelegt (Rolle={role})") + + +if __name__ == "__main__": + init_db() + username = input("Admin-E-Mail [admin@localhost]: ") or "admin@localhost" + password = getpass.getpass("Passwort: ") + password_2 = getpass.getpass("Passwort wiederholen: ") + if password != password_2: + print("Passwörter stimmen nicht überein.") + raise SystemExit(1) + create_user(username, password, role="admin", comment="Initialer Admin-Benutzer") + print("Datenbankinitialisierung abgeschlossen.") diff --git a/packages/auth_service/requirements.txt b/packages/auth_service/requirements.txt new file mode 100644 index 0000000000..2306ef413b --- /dev/null +++ b/packages/auth_service/requirements.txt @@ -0,0 +1,5 @@ +Flask==3.1.2 +passlib==1.7.4 +PyJWT==2.10.1 +Requests==2.32.5 +waitress==3.0.2 From 220a92b52798b1a6aee03909e8bc9d05553e3d53 Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Thu, 13 Nov 2025 12:49:37 +0100 Subject: [PATCH 12/76] Reduces client inactivity timeout to 30 minutes --- data/config/mosquitto/mosquitto.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/config/mosquitto/mosquitto.conf b/data/config/mosquitto/mosquitto.conf index bc9b0041a6..0c98e4d2b4 100644 --- a/data/config/mosquitto/mosquitto.conf +++ b/data/config/mosquitto/mosquitto.conf @@ -12,7 +12,7 @@ log_timestamp_format %Y-%m-%dT%H:%M:%S per_listener_settings true # prevent too many inactive connections from buggy clients -# closes inactive connections after 4 hours -persistent_client_expiration 4h +# closes inactive connections after 30 minutes +persistent_client_expiration 30m include_dir /etc/mosquitto/conf.d From 661eb4c69d018cfad2190aa5f5b666725b8a2fc9 Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Fri, 14 Nov 2025 11:27:57 +0100 Subject: [PATCH 13/76] cleanup --- packages/auth_service/auth_server.py | 83 ++++++++++++++++------------ packages/auth_service/init_db.py | 3 +- 2 files changed, 49 insertions(+), 37 deletions(-) diff --git a/packages/auth_service/auth_server.py b/packages/auth_service/auth_server.py index 7955e8759f..d44b0fdb07 100644 --- a/packages/auth_service/auth_server.py +++ b/packages/auth_service/auth_server.py @@ -2,8 +2,9 @@ # auth_server.py — Flask Auth-Service mit JWT, Refresh-Rotation, DynSec-Integration, SQlite # Python 3.11 -from typing import Optional -from flask import Flask, request, jsonify, make_response +from datetime import datetime, timedelta +from typing import Optional, Union +from flask import Flask, request, jsonify, make_response, Response import os import sqlite3 from passlib.hash import bcrypt @@ -20,7 +21,8 @@ MOSQ_ADMIN_PASS = os.environ.get("MOSQ_ADMIN_PASS", "changeme") MOSQ_ROLE = os.environ.get("MOSQ_ROLE", "user") TLS_ONLY = os.environ.get("TLS_ONLY", "1") == "1" # wenn True cookies mit Secure setzen -COOKIE_NAME = "mqtt_auth" +COOKIE_NAME = "openwb_auth" +TOKEN_SERVER_URL = os.environ.get("TOKEN_SERVER_URL", "https://openwb.de/forgotpassword/send_token.php") # ---------------------- # Flask App @@ -31,19 +33,25 @@ # ---------------------- # DB Hilfsfunktionen # ---------------------- -def db_connect(): +def db_connect() -> sqlite3.Connection: db_connection = sqlite3.connect(DB_PATH, detect_types=sqlite3.PARSE_DECLTYPES) db_connection.row_factory = sqlite3.Row return db_connection +def db_timestamp_to_epoch_seconds(ts: Optional[datetime]) -> Optional[int]: + if ts is None: + return None + return int(ts.timestamp()) + + # ---------------------- # Nutzer-Logik # ---------------------- -def get_user(email): +def get_user(email: str) -> Optional[sqlite3.Row]: db_connection = db_connect() cur = db_connection.execute( - "SELECT email, password_hash, first_name, last_name, role, disabled, comment FROM users WHERE email = ?", + "SELECT * FROM users WHERE email = ?", (email,) ) row = cur.fetchone() @@ -51,27 +59,27 @@ def get_user(email): return row -def verify_user_password(email, password): +def verify_user_password(email: str, password: str) -> bool: row = get_user(email) - if not row or row["disabled"]: - return False - try: - return bcrypt.verify(password, row["password_hash"]) - except Exception: - return False + return row and not row["disabled"] and bcrypt.verify(password, row["password_hash"]) + + +def verify_user_token(email: str, token: str) -> bool: + row = get_user(email) + return row and not row["disabled"] and bcrypt.verify(token, row["password_token_hash"]) and \ + row["password_token_expires_at"] and row["password_token_expires_at"] > datetime.now() -def verify_user_role(email, role="admin"): +def verify_user_role(email: str, role: str = "admin") -> bool: row = get_user(email) - if row and not row["disabled"] and row["role"] == role: - return True - return False + return row and not row["disabled"] and row["role"] == role # ---------------------- # Auth-Hilfsfunktion # ---------------------- -def get_authenticated_email(required_role: Optional[str] = None): +def get_authenticated_email( + required_role: Optional[str] = None) -> tuple[Optional[str], Optional[tuple[Response, int]]]: """ Prüft das Auth-Cookie und optional die Rolle. Rückgabe: (email, None) bei Erfolg oder (None, (jsonify..., status)) bei Fehler. @@ -184,11 +192,11 @@ def get_authenticated_email(required_role: Optional[str] = None): # ---------------------- # Web API Endpoints (Login / Refresh / MQTT credentials / Logout / Health) # ---------------------- -def set_cookie(resp, name, value, expires=None): +def set_cookie(resp: Response, key: str, value, expires: Optional[Union[str, datetime, int, float]] = None) -> None: resp.set_cookie( - name, + key, value, - httponly=False, + httponly=True, secure=TLS_ONLY, samesite="Strict", expires=expires @@ -196,7 +204,7 @@ def set_cookie(resp, name, value, expires=None): @app.post("/api/login") -def web_login(): +def web_login() -> Response: data: dict = request.get_json(force=True) email: Optional[str] = data.get("email") password: Optional[str] = data.get("password") @@ -212,7 +220,7 @@ def web_login(): @app.post("/api/logout") -def logout(): +def logout() -> Response: resp = make_response(jsonify(success=True)) # Cookie löschen set_cookie(resp, COOKIE_NAME, "", expires=0) @@ -220,7 +228,7 @@ def logout(): @app.get("/api/health") -def health(): +def health() -> Response: return jsonify(status="ok") @@ -233,12 +241,12 @@ def health(): # User-Create Endpoint # ---------------------- @app.post("/admin/create_user") -def admin_create_user(): +def admin_create_user() -> Response: # Auth prüfen _, err = get_authenticated_email(required_role="admin") if err: return err - data = request.get_json(force=True) + data: dict = request.get_json(force=True) email = data.get("email") password = data.get("password") first_name = data.get("first_name") @@ -267,12 +275,12 @@ def admin_create_user(): # User-Update Endpoint # ---------------------- @app.post("/admin/update_user") -def admin_update_user(): +def admin_update_user() -> Response: # Auth prüfen _, err = get_authenticated_email(required_role="admin") if err: return err - data = request.get_json(force=True) + data: dict = request.get_json(force=True) email = data.get("email") first_name = data.get("first_name") last_name = data.get("last_name") @@ -300,12 +308,12 @@ def admin_update_user(): # User-Delete Endpoint # ---------------------- @app.post("/admin/delete_user") -def admin_delete_user(): +def admin_delete_user() -> Response: # Auth prüfen _, err = get_authenticated_email(required_role="admin") if err: return err - data = request.get_json(force=True) + data: dict = request.get_json(force=True) email = data.get("email") if not email: return jsonify(error="email required"), 400 @@ -326,12 +334,12 @@ def admin_delete_user(): # User-Password Endpoint # ---------------------- @app.post("/admin/update_password") -def admin_update_password(): +def admin_update_password() -> Response: # Auth prüfen _, err = get_authenticated_email(required_role="admin") if err: return err - data = request.get_json(force=True) + data: dict = request.get_json(force=True) email = data.get("email") password = data.get("password") if not email or not password: @@ -348,23 +356,25 @@ def admin_update_password(): conn.close() if modified == 0: return jsonify(error=f"user with email '{email}' not found"), 409 - return jsonify(success=True, email=email) + return jsonify(success=True) # ---------------------- # Get-Users Endpoint # ---------------------- @app.get("/admin/get_users") -def admin_get_users(): +def admin_get_users() -> Response: # Auth prüfen - email, err = get_authenticated_email(required_role="admin") + _, err = get_authenticated_email(required_role="admin") if err: return err conn = db_connect() cur = conn.execute("SELECT email, first_name, last_name, comment, role, disabled, created_at FROM users") users = [dict(row) for row in cur.fetchall()] + for user in users: + user["created_at"] = db_timestamp_to_epoch_seconds(user["created_at"]) conn.close() - return jsonify(users=users, requested_by=email) + return jsonify(users=users) # ---------------------- @@ -375,6 +385,7 @@ def admin_get_users(): host = os.environ.get("LISTEN_HOST", "127.0.0.1") port = int(os.environ.get("LISTEN_PORT", "3000")) debug = os.environ.get("AUTH_DEBUG", "0") == "1" + print(f"Starting Auth-Service on {host}:{port} (Debug={debug})") # Starte mit waitress, falls verfügbar; sonst Fallback auf Flask-Dev-Server try: from waitress import serve diff --git a/packages/auth_service/init_db.py b/packages/auth_service/init_db.py index 6506188516..a6e1b403ca 100644 --- a/packages/auth_service/init_db.py +++ b/packages/auth_service/init_db.py @@ -11,6 +11,7 @@ def init_db(): db_connection = sqlite3.connect(DB_PATH) db_cursor = db_connection.cursor() + # Alle TIMESTAMP-Spalten werden als UTC gespeichert! db_cursor.executescript(""" CREATE TABLE IF NOT EXISTS users ( email TEXT PRIMARY KEY, @@ -20,7 +21,7 @@ def init_db(): role TEXT NOT NULL DEFAULT 'viewer', disabled INTEGER NOT NULL DEFAULT 0, comment TEXT, - password_token TEXT, + password_token_hash TEXT, password_token_expires_at TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); From 0e4bbb8f5879a4a55dc55e2faf2111ab94723cf4 Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Fri, 14 Nov 2025 11:28:37 +0100 Subject: [PATCH 14/76] user endpoints / token handling --- packages/auth_service/auth_server.py | 140 ++++++++++++++++++++- packages/auth_service/demo_token_client.py | 118 +++++++++++++++++ 2 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 packages/auth_service/demo_token_client.py diff --git a/packages/auth_service/auth_server.py b/packages/auth_service/auth_server.py index d44b0fdb07..02800a01dc 100644 --- a/packages/auth_service/auth_server.py +++ b/packages/auth_service/auth_server.py @@ -8,8 +8,9 @@ import os import sqlite3 from passlib.hash import bcrypt +from secrets import token_urlsafe # import secrets -# import requests +import requests # import time # ---------------------- @@ -232,6 +233,143 @@ def health() -> Response: return jsonify(status="ok") +# ---------------------- +# User Endpoints +# ---------------------- + + +# ---------------------- +# User-Me Endpoint +# ---------------------- +@app.get("/user/me") +def user_me() -> Response: + email, err = get_authenticated_email() + if err: + return err + row = get_user(email) + if not row or row["disabled"]: + return jsonify(error="user not found"), 404 + user_info = { + "email": row["email"], + "first_name": row["first_name"], + "last_name": row["last_name"], + "role": row["role"], + "comment": row["comment"], + "created_at": db_timestamp_to_epoch_seconds(row["created_at"]), + "token_expires_at": db_timestamp_to_epoch_seconds(row["password_token_expires_at"]) + } + return jsonify(user=user_info) + + +# ---------------------- +# User-Update-Password Endpoint +# ---------------------- +@app.post("/user/update_password") +def user_update_password() -> Response: + data: dict = request.get_json(force=True) + old_password = data.get("old_password") + new_password = data.get("new_password") + email = data.get("email") + token_used = False + if old_password is None or new_password is None: + return jsonify(error="old_password and new_password required"), 400 + # check for passwort token + if not verify_user_token(email, old_password): + email, err = get_authenticated_email() + if err: + return err + if not verify_user_password(email, old_password): + return jsonify(error="invalid old_password or token"), 401 + else: + token_used = True + pw_hash = bcrypt.hash(new_password) + conn = db_connect() + conn.execute( + "UPDATE users SET password_hash = ?, password_token_hash = NULL, password_token_expires_at = NULL " + "WHERE email = ?", + (pw_hash, email) + ) + conn.commit() + conn.close() + + resp = make_response(jsonify(success=True, token_used=token_used)) + # Cookie setzen + set_cookie(resp, COOKIE_NAME, f"{email}:{new_password}", expires=None) + return resp + + +# ---------------------- +# User-Create-Password-Token Endpoint +# ---------------------- +@app.post("/user/create_password_token") +def user_generate_token() -> Response: + timeout = 10 # seconds + data: dict = request.get_json(force=True) + email = data.get("email") + # create random token + token = token_urlsafe(6) + token_hash = bcrypt.hash(token) + expires_at = datetime.now() + timedelta(hours=1) + conn = db_connect() + conn.execute( + "UPDATE users SET password_token_hash = ?, password_token_expires_at = ? " + "WHERE email = ?", + (token_hash, expires_at, email) + ) + conn.commit() + conn.close() + # send token to user via email gateway + error = None + try: + payload = {"email": email, "token": token} + print(f"Sending token to {TOKEN_SERVER_URL}: {payload}") + headers = { + 'Content-Type': 'application/json', + 'User-Agent': 'Token-Client/1.0', + 'charset': 'utf-8' + } + resp = requests.post( + url=TOKEN_SERVER_URL, + json=payload, + headers=headers, + timeout=timeout + ) + except requests.exceptions.Timeout: + error = f"Error: request timed out after {timeout}s" + except requests.exceptions.ConnectionError: + error = f"Error: connection to {TOKEN_SERVER_URL} failed" + except requests.RequestException as e: + error = f"HTTP-Error: {e}" + print(f"{resp.status_code}: {resp.text}") + if resp.status_code != 200: + error = f"Error: server returned status {resp.status_code}" + if error is not None: + return jsonify(error=error), 500 + return jsonify(success=True, token=token, expires_at=expires_at.isoformat()) + + +# ---------------------- +# User-Update Endpoint +# ---------------------- +@app.post("/user/update") +def user_update() -> Response: + email, err = get_authenticated_email() + if err: + return err + data: dict = request.get_json(force=True) + first_name = data.get("first_name") + last_name = data.get("last_name") + comment = data.get("comment") + conn = db_connect() + conn.execute( + "UPDATE users SET first_name = ?, last_name = ?, comment = ? " + "WHERE email = ?", + (first_name, last_name, comment, email) + ) + conn.commit() + conn.close() + return jsonify(success=True) + # ---------------------- # Admin Endpoints # ---------------------- diff --git a/packages/auth_service/demo_token_client.py b/packages/auth_service/demo_token_client.py new file mode 100644 index 0000000000..c8c1a9246f --- /dev/null +++ b/packages/auth_service/demo_token_client.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python3 +""" +Einfacher Token-Client für das Forgot-Password-System. +Sendet E-Mail und Token an den Server. +""" + +import argparse +import json +import sys + +try: + import requests +except ImportError: + print("Bitte zuerst installieren: pip install requests", file=sys.stderr) + sys.exit(2) + + +def main(): + parser = argparse.ArgumentParser( + description="Token-Client: sendet E-Mail und Token an den Server.", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +Beispiele: + python3 token_client.py --email user@example.com --token "mein-geheimes-token" + python3 token_client.py -e user@example.com -t "token123" --debug + python3 token_client.py -e user@example.com -t "token123" --url https://openwb.de/forgotpassword/send_token.php + """ + ) + + parser.add_argument("-e", "--email", required=True, help="E-Mail-Adresse") + parser.add_argument("-t", "--token", required=True, help="Token zum Übertragen") + parser.add_argument("--url", default="https://openwb.de/forgotpassword/send_token.php", + help="Server-URL (Default: https://openwb.de/forgotpassword/send_token.php)") + parser.add_argument("--timeout", type=int, default=15, + help="HTTP-Timeout in Sekunden (Default: 15)") + parser.add_argument("--debug", action="store_true", + help="Debug-Ausgaben aktivieren") + + args = parser.parse_args() + + # Validierung + if "@" not in args.email: + print("Fehler: Ungültige E-Mail-Adresse", file=sys.stderr) + sys.exit(1) + + if not args.token.strip(): + print("Fehler: Token darf nicht leer sein", file=sys.stderr) + sys.exit(1) + + payload = { + "email": args.email, + "token": args.token, + } + + if args.debug: + print(f"DEBUG: URL: {args.url}") + print(f"DEBUG: Payload: {json.dumps(payload, indent=2)}") + print(f"DEBUG: Timeout: {args.timeout}s") + print("DEBUG: Sende Request...") + + try: + headers = { + 'Content-Type': 'application/json', + 'User-Agent': 'Token-Client/1.0' + } + + resp = requests.post( + args.url, + json=payload, + headers=headers, + timeout=args.timeout + ) + + except requests.exceptions.Timeout: + print(f"Fehler: Timeout nach {args.timeout} Sekunden", file=sys.stderr) + sys.exit(1) + except requests.exceptions.ConnectionError: + print(f"Fehler: Kann keine Verbindung zu {args.url} herstellen", file=sys.stderr) + sys.exit(1) + except requests.RequestException as e: + print(f"HTTP-Fehler: {e}", file=sys.stderr) + sys.exit(1) + + # Response anzeigen + print(f"✓ POST {args.url}") + print(f"✓ Status: {resp.status_code}") + + if args.debug: + print(f"DEBUG: Response Headers: {dict(resp.headers)}") + + # Content anzeigen + content_type = resp.headers.get("Content-Type", "").lower() + if "application/json" in content_type: + try: + data = resp.json() + print("Response:") + print(json.dumps(data, ensure_ascii=False, indent=2)) + + # Status auswerten + if resp.status_code == 200 and data.get('ok'): + print("\n✓ Erfolgreich! Prüfen Sie Ihr E-Mail-Postfach.") + elif data.get('error'): + print(f"\n✗ Fehler: {data['error']}", file=sys.stderr) + sys.exit(1) + + except json.JSONDecodeError: + print("Response (kein gültiges JSON):") + print(resp.text) + else: + print("Response:") + print(resp.text) + + if resp.status_code >= 400: + sys.exit(1) + + +if __name__ == "__main__": + main() From f49cafb3a4686743266f7dc65708ca519f418cda Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Mon, 17 Nov 2025 12:23:32 +0100 Subject: [PATCH 15/76] modify token handling / cleanup --- packages/auth_service/auth_server.py | 175 ++++++++++++++----------- packages/auth_service/requirements.txt | 1 - 2 files changed, 98 insertions(+), 78 deletions(-) diff --git a/packages/auth_service/auth_server.py b/packages/auth_service/auth_server.py index 02800a01dc..0c4e2d3332 100644 --- a/packages/auth_service/auth_server.py +++ b/packages/auth_service/auth_server.py @@ -3,6 +3,8 @@ # Python 3.11 from datetime import datetime, timedelta +from random import randrange +from time import sleep from typing import Optional, Union from flask import Flask, request, jsonify, make_response, Response import os @@ -40,10 +42,10 @@ def db_connect() -> sqlite3.Connection: return db_connection -def db_timestamp_to_epoch_seconds(ts: Optional[datetime]) -> Optional[int]: - if ts is None: +def db_timestamp_to_epoch_seconds(timestamp: Optional[datetime]) -> Optional[int]: + if timestamp is None: return None - return int(ts.timestamp()) + return int(timestamp.timestamp()) # ---------------------- @@ -51,11 +53,11 @@ def db_timestamp_to_epoch_seconds(ts: Optional[datetime]) -> Optional[int]: # ---------------------- def get_user(email: str) -> Optional[sqlite3.Row]: db_connection = db_connect() - cur = db_connection.execute( + db_cursor = db_connection.execute( "SELECT * FROM users WHERE email = ?", (email,) ) - row = cur.fetchone() + row = db_cursor.fetchone() db_connection.close() return row @@ -214,10 +216,10 @@ def web_login() -> Response: if not verify_user_password(email, password): return jsonify(error="invalid credentials"), 401 - resp = make_response(jsonify(success=True)) + response = make_response(jsonify(success=True)) # Cookie setzen - set_cookie(resp, COOKIE_NAME, f"{email}:{password}", expires=None) - return resp + set_cookie(response, COOKIE_NAME, f"{email}:{password}", expires=None) + return response @app.post("/api/logout") @@ -283,19 +285,19 @@ def user_update_password() -> Response: else: token_used = True pw_hash = bcrypt.hash(new_password) - conn = db_connect() - conn.execute( + db_connection = db_connect() + db_connection.execute( "UPDATE users SET password_hash = ?, password_token_hash = NULL, password_token_expires_at = NULL " "WHERE email = ?", (pw_hash, email) ) - conn.commit() - conn.close() + db_connection.commit() + db_connection.close() - resp = make_response(jsonify(success=True, token_used=token_used)) + response = make_response(jsonify(success=True, token_used=token_used)) # Cookie setzen - set_cookie(resp, COOKIE_NAME, f"{email}:{new_password}", expires=None) - return resp + set_cookie(response, COOKIE_NAME, f"{email}:{new_password}", expires=None) + return response # ---------------------- @@ -306,32 +308,50 @@ def user_generate_token() -> Response: timeout = 10 # seconds data: dict = request.get_json(force=True) email = data.get("email") - # create random token + if not email: + return jsonify(error="email required"), 400 token = token_urlsafe(6) token_hash = bcrypt.hash(token) expires_at = datetime.now() + timedelta(hours=1) - conn = db_connect() - conn.execute( + + db_connection = db_connect() + db_cursor = db_connection.execute( "UPDATE users SET password_token_hash = ?, password_token_expires_at = ? " "WHERE email = ?", (token_hash, expires_at, email) ) - conn.commit() - conn.close() + affected_rows = db_cursor.rowcount + db_connection.commit() + db_connection.close() + + if affected_rows == 0: + print(f"Password token requested for unknown email: {email}") + # report success even if email not found to avoid user enumeration + sleep(randrange(5, 25) * 0.1) # künstliche Verzögerung + return jsonify(success=True,) + # send token to user via email gateway error = None try: - payload = {"email": email, "token": token} - print(f"Sending token to {TOKEN_SERVER_URL}: {payload}") - headers = { - 'Content-Type': 'application/json', - 'User-Agent': 'Token-Client/1.0', - 'charset': 'utf-8' + payload = { + "email": email, + "subject": "openWB Passwort-Reset", + "message": "Hallo,\n\n" + "Du hast in einer openWB ein Passwort-Reset angefordert.\n" + "Bitte verwende den folgenden Token, um Dein Passwort zurückzusetzen:\n\n" + f"Token: {token}\n\n" + "Dieser Token ist 1 Stunde gültig.\n\n" + "Falls Du kein Passwort-Reset angefordert hast, kannst Du diese Nachricht ignorieren." } - resp = requests.post( + print(f"Sending token to {TOKEN_SERVER_URL}: {payload}") + response = requests.post( url=TOKEN_SERVER_URL, json=payload, - headers=headers, + headers={ + 'Content-Type': 'application/json', + 'User-Agent': 'Token-Client/1.0', + 'charset': 'utf-8' + }, timeout=timeout ) except requests.exceptions.Timeout: @@ -340,12 +360,10 @@ def user_generate_token() -> Response: error = f"Error: connection to {TOKEN_SERVER_URL} failed" except requests.RequestException as e: error = f"HTTP-Error: {e}" - print(f"{resp.status_code}: {resp.text}") - if resp.status_code != 200: - error = f"Error: server returned status {resp.status_code}" - if error is not None: - return jsonify(error=error), 500 - return jsonify(success=True, token=token, expires_at=expires_at.isoformat()) + print(f"{response.status_code}: {response.text}") + if error is not None or response.status_code != 200: + return jsonify(error=error or f"Error: server returned status {response.status_code}"), 500 + return jsonify(success=True,) # ---------------------- @@ -353,21 +371,21 @@ def user_generate_token() -> Response: # ---------------------- @app.post("/user/update") def user_update() -> Response: - email, err = get_authenticated_email() - if err: - return err + email, error = get_authenticated_email() + if error: + return error data: dict = request.get_json(force=True) first_name = data.get("first_name") last_name = data.get("last_name") comment = data.get("comment") - conn = db_connect() - conn.execute( + db_connection = db_connect() + db_connection.execute( "UPDATE users SET first_name = ?, last_name = ?, comment = ? " "WHERE email = ?", (first_name, last_name, comment, email) ) - conn.commit() - conn.close() + db_connection.commit() + db_connection.close() return jsonify(success=True) # ---------------------- @@ -381,9 +399,9 @@ def user_update() -> Response: @app.post("/admin/create_user") def admin_create_user() -> Response: # Auth prüfen - _, err = get_authenticated_email(required_role="admin") - if err: - return err + _, error = get_authenticated_email(required_role="admin") + if error: + return error data: dict = request.get_json(force=True) email = data.get("email") password = data.get("password") @@ -394,18 +412,18 @@ def admin_create_user() -> Response: if not email or not password: return jsonify(error="email and password required"), 400 pw_hash = bcrypt.hash(password) - conn = db_connect() + db_connection = db_connect() try: - conn.execute( + db_connection.execute( "INSERT INTO users (email, password_hash, first_name, last_name, role, disabled, comment) " "VALUES (?, ?, ?, ?, ?, 0, ?)", (email, pw_hash, first_name, last_name, role, comment) ) - conn.commit() + db_connection.commit() except sqlite3.IntegrityError: return jsonify(error=f"user with email '{email}' already exists"), 409 finally: - conn.close() + db_connection.close() return jsonify(success=True, email=email) @@ -427,18 +445,18 @@ def admin_update_user() -> Response: comment = data.get("comment") if not email: return jsonify(error="email required"), 400 - conn = db_connect() + db_connection = db_connect() try: - conn.execute( + db_connection.execute( "UPDATE users SET first_name = ?, last_name = ?, role = ?, disabled = ?, comment = ? " "WHERE email = ?", (first_name, last_name, role, disabled, comment, email) ) - conn.commit() + db_connection.commit() except sqlite3.IntegrityError: return jsonify(error=f"user with email '{email}' already exists"), 409 finally: - conn.close() + db_connection.close() return jsonify(success=True, email=email) @@ -448,22 +466,22 @@ def admin_update_user() -> Response: @app.post("/admin/delete_user") def admin_delete_user() -> Response: # Auth prüfen - _, err = get_authenticated_email(required_role="admin") - if err: - return err + _, error = get_authenticated_email(required_role="admin") + if error: + return error data: dict = request.get_json(force=True) email = data.get("email") if not email: return jsonify(error="email required"), 400 - conn = db_connect() - cur = conn.execute( + db_connection = db_connect() + db_cursor = db_connection.execute( "DELETE FROM users WHERE email = ?", (email,) ) - deleted = cur.rowcount - conn.commit() - conn.close() - if deleted == 0: + deleted_rows = db_cursor.rowcount + db_connection.commit() + db_connection.close() + if deleted_rows == 0: return jsonify(error="user not found"), 404 return jsonify(success=True, email=email) @@ -474,25 +492,25 @@ def admin_delete_user() -> Response: @app.post("/admin/update_password") def admin_update_password() -> Response: # Auth prüfen - _, err = get_authenticated_email(required_role="admin") - if err: - return err + _, error = get_authenticated_email(required_role="admin") + if error: + return error data: dict = request.get_json(force=True) email = data.get("email") password = data.get("password") if not email or not password: return jsonify(error="email and password required"), 400 pw_hash = bcrypt.hash(password) - conn = db_connect() - cur = conn.execute( + db_connection = db_connect() + db_cursor = db_connection.execute( "UPDATE users SET password_hash = ? " "WHERE email = ?", (pw_hash, email) ) - modified = cur.rowcount - conn.commit() - conn.close() - if modified == 0: + modified_rows = db_cursor.rowcount + db_connection.commit() + db_connection.close() + if modified_rows == 0: return jsonify(error=f"user with email '{email}' not found"), 409 return jsonify(success=True) @@ -503,15 +521,18 @@ def admin_update_password() -> Response: @app.get("/admin/get_users") def admin_get_users() -> Response: # Auth prüfen - _, err = get_authenticated_email(required_role="admin") - if err: - return err - conn = db_connect() - cur = conn.execute("SELECT email, first_name, last_name, comment, role, disabled, created_at FROM users") - users = [dict(row) for row in cur.fetchall()] + _, error = get_authenticated_email(required_role="admin") + if error: + return error + db_connection = db_connect() + db_cursor = db_connection.execute( + "SELECT email, first_name, last_name, comment, role, disabled, created_at " + "FROM users" + ) + users = [dict(row) for row in db_cursor.fetchall()] for user in users: user["created_at"] = db_timestamp_to_epoch_seconds(user["created_at"]) - conn.close() + db_connection.close() return jsonify(users=users) diff --git a/packages/auth_service/requirements.txt b/packages/auth_service/requirements.txt index 2306ef413b..3d5abc57aa 100644 --- a/packages/auth_service/requirements.txt +++ b/packages/auth_service/requirements.txt @@ -1,5 +1,4 @@ Flask==3.1.2 passlib==1.7.4 -PyJWT==2.10.1 Requests==2.32.5 waitress==3.0.2 From e742462cd68fe55751e4dc8d6cb86c6278df1b49 Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Tue, 18 Nov 2025 12:54:44 +0100 Subject: [PATCH 16/76] refactoring --- packages/auth_service/auth_server.py | 498 +++++++++++++-------- packages/auth_service/demo_token_client.py | 118 ----- packages/auth_service/init_db.py | 57 --- packages/auth_service/requirements.txt | 4 - requirements.txt | 3 + 5 files changed, 303 insertions(+), 377 deletions(-) mode change 100644 => 100755 packages/auth_service/auth_server.py delete mode 100644 packages/auth_service/demo_token_client.py delete mode 100644 packages/auth_service/init_db.py delete mode 100644 packages/auth_service/requirements.txt diff --git a/packages/auth_service/auth_server.py b/packages/auth_service/auth_server.py old mode 100644 new mode 100755 index 0c4e2d3332..e3a7314765 --- a/packages/auth_service/auth_server.py +++ b/packages/auth_service/auth_server.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# auth_server.py — Flask Auth-Service mit JWT, Refresh-Rotation, DynSec-Integration, SQlite +# auth_server.py — Flask Auth-Service with DynSec-Integration, SQlite # Python 3.11 from datetime import datetime, timedelta @@ -10,22 +10,27 @@ import os import sqlite3 from passlib.hash import bcrypt -from secrets import token_urlsafe -# import secrets +from secrets import token_urlsafe, token_hex import requests -# import time +from time import time +from inspect import currentframe # ---------------------- -# Konfiguration via ENV +# Configuration via ENV # ---------------------- -DB_PATH = os.environ.get("AUTH_DB", "./auth.db") +DB_PATH = os.environ.get("AUTH_DB", "/home/openwb/auth.db") MOSQUITTO_API = os.environ.get("MOSQUITTO_API", "http://localhost:8080/dynamic-security/v1") MOSQ_ADMIN_USER = os.environ.get("MOSQ_ADMIN_USER", "admin") MOSQ_ADMIN_PASS = os.environ.get("MOSQ_ADMIN_PASS", "changeme") MOSQ_ROLE = os.environ.get("MOSQ_ROLE", "user") -TLS_ONLY = os.environ.get("TLS_ONLY", "1") == "1" # wenn True cookies mit Secure setzen +TLS_ONLY = os.environ.get("TLS_ONLY", "1") == "1" # if True set cookies with Secure flag COOKIE_NAME = "openwb_auth" TOKEN_SERVER_URL = os.environ.get("TOKEN_SERVER_URL", "https://openwb.de/forgotpassword/send_token.php") +DEFAULT_ADMIN_USER = {"username": "admin", "email": "admin@localhost", "password": "openWB#Admin"} + +host = os.environ.get("LISTEN_HOST", "127.0.0.1") +port = int(os.environ.get("LISTEN_PORT", "3000")) +debug = os.environ.get("AUTH_DEBUG", "0") == "1" # ---------------------- # Flask App @@ -34,162 +39,214 @@ # ---------------------- -# DB Hilfsfunktionen +# DB Helpers # ---------------------- def db_connect() -> sqlite3.Connection: + """Creates a connection to the SQLite database.""" db_connection = sqlite3.connect(DB_PATH, detect_types=sqlite3.PARSE_DECLTYPES) db_connection.row_factory = sqlite3.Row + print_debug("Connected to DB") return db_connection def db_timestamp_to_epoch_seconds(timestamp: Optional[datetime]) -> Optional[int]: + """Translates a DB TIMESTAMP to epoch seconds.""" if timestamp is None: return None return int(timestamp.timestamp()) +def init_db(): + """Initializes the database and creates the initial admin user.""" + db_connection = db_connect() + db_cursor = db_connection.cursor() + # All TIMESTAMP are stored as ISO8601 strings in UTC + db_cursor.execute(""" + CREATE TABLE IF NOT EXISTS users ( + username TEXT PRIMARY KEY, + email TEXT UNIQUE NOT NULL, + password_hash TEXT NOT NULL, + first_name TEXT, + last_name TEXT, + role TEXT NOT NULL DEFAULT 'viewer', + disabled INTEGER NOT NULL DEFAULT 0, + comment TEXT, + password_token_hash TEXT, + password_token_expires_at TIMESTAMP, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ); + """) + db_connection.commit() + print("DB initialisiert:", DB_PATH) + pw_hash = bcrypt.hash(DEFAULT_ADMIN_USER["password"]) + db_cursor.execute( + "INSERT OR REPLACE INTO users (username, email, password_hash, role, comment) " + "VALUES (?, ?, ?, ?, ?);", + (DEFAULT_ADMIN_USER["username"], DEFAULT_ADMIN_USER["email"], pw_hash, "admin", "Initialer Admin-Benutzer") + ) + db_connection.commit() + print(f"Initialen Admin-Benutzer angelegt: {DEFAULT_ADMIN_USER['username']} / " + f"{DEFAULT_ADMIN_USER['email']} / {DEFAULT_ADMIN_USER['password']}") + print("Bitte Passwort nach dem ersten Login ändern!") + db_connection.close() + # set file permissions to owner read/write only + os.chmod(DB_PATH, 0o600) + + +def check_default_admin_user_exists(): + """Checks if the default admin user exists.""" + pw_hash = bcrypt.hash(DEFAULT_ADMIN_USER["password"]) + db_connection = db_connect() + db_cursor = db_connection.execute( + "SELECT COUNT(*) AS count FROM users WHERE username = ? and password_hash = ?", + (DEFAULT_ADMIN_USER["username"], pw_hash) + ) + row = db_cursor.fetchone() + db_connection.close() + return row["count"] > 0 + + # ---------------------- -# Nutzer-Logik +# User Helpers # ---------------------- -def get_user(email: str) -> Optional[sqlite3.Row]: +def get_user(username: str) -> Optional[sqlite3.Row]: + """Fetches a user row by username.""" db_connection = db_connect() db_cursor = db_connection.execute( - "SELECT * FROM users WHERE email = ?", - (email,) + "SELECT * FROM users WHERE username = ?", + (username,) ) row = db_cursor.fetchone() db_connection.close() + print_debug(f"Fetched user '{username}': {'found' if row else 'not found'}") return row -def verify_user_password(email: str, password: str) -> bool: - row = get_user(email) - return row and not row["disabled"] and bcrypt.verify(password, row["password_hash"]) +def get_user_by_email(email: str) -> Optional[sqlite3.Row]: + """Fetches a user row by email.""" + db_connection = db_connect() + db_cursor = db_connection.execute( + "SELECT * FROM users WHERE email = ?", + (email,) + ) + row = db_cursor.fetchone() + db_connection.close() + print_debug(f"Fetched user by email '{email}': {'found' if row else 'not found'}") + return row -def verify_user_token(email: str, token: str) -> bool: - row = get_user(email) - return row and not row["disabled"] and bcrypt.verify(token, row["password_token_hash"]) and \ - row["password_token_expires_at"] and row["password_token_expires_at"] > datetime.now() +def verify_user_password(username: str, password: str) -> bool: + """Verifies a user's password. Returns (is_valid, actual_username). + Parameter 'username' can be either the username or the email. + """ + row = get_user(username) + if not row: + # try email as username + row = get_user_by_email(username) + user_valid = row and not row["disabled"] and bcrypt.verify(password, row["password_hash"]) + print_debug(f"Password verification for user '{username}': {'valid' if user_valid else 'invalid'}") + return (user_valid, row["username"] if row else None) + + +def verify_user_token(username: str, token: str) -> bool: + """Verifies a user's password reset token. + Parameter 'username' can be either the username or the email. + """ + print_debug(f"Verifying token for user '{username}'") + row = get_user(username) + if not row: + # try email as username + row = get_user_by_email(username) + token_valid = ( + row + and not row["disabled"] + and row["password_token_hash"] + and bcrypt.verify(token, row["password_token_hash"]) + and row["password_token_expires_at"] + and row["password_token_expires_at"] > datetime.now() + ) + print_debug(f"Token verification for user '{username}': {'valid' if token_valid else 'invalid'}") + return token_valid -def verify_user_role(email: str, role: str = "admin") -> bool: - row = get_user(email) - return row and not row["disabled"] and row["role"] == role +def verify_user_role(username: str, role: str = "admin") -> bool: + """Verifies a user's role.""" + row = get_user(username) + role_valid = row and not row["disabled"] and row["role"] == role + print_debug(f"Role verification for user '{username}': {'valid' if role_valid else 'invalid'}") + return role_valid # ---------------------- -# Auth-Hilfsfunktion +# Auth Helpers # ---------------------- -def get_authenticated_email( +def get_authenticated_username( required_role: Optional[str] = None) -> tuple[Optional[str], Optional[tuple[Response, int]]]: - """ - Prüft das Auth-Cookie und optional die Rolle. - Rückgabe: (email, None) bei Erfolg oder (None, (jsonify..., status)) bei Fehler. + """Verifies the authentication cookie and optional role. + Returns (username, None) if authenticated, otherwise (None, (Response, status_code)) """ auth_data = request.cookies.get(COOKIE_NAME) - email, password = (auth_data or ":").split(":", 1) - if not verify_user_password(email, password): - return None, (jsonify(error="Not Authenticated"), 401) - if required_role and not verify_user_role(email, role=required_role): - return None, (jsonify(error="Forbidden"), 403) - return email, None + username, password = (auth_data or ":").split(":", 1) + result = username, None + user_valid, _ = verify_user_password(username, password) + if not user_valid: + result = None, (jsonify(error="Not Authenticated"), 401) + if required_role and not verify_user_role(username, role=required_role): + result = None, (jsonify(error="Forbidden"), 403) + print_debug(f"Authenticated user: '{username}' -> {'success' if result[0] else 'failure'}") + return result + + +# ---------------------- +# General Helpers +# ---------------------- +def print_debug(msg: str) -> None: + """Prints a debug message if AUTH_DEBUG is enabled. + """ + if debug: + frame = currentframe().f_back + lineno = frame.f_lineno + filename = frame.f_code.co_filename + print(f"[DEBUG][{filename}]:{lineno} {msg}") # ---------------------- # Mosquitto Dynamic Security helpers # ---------------------- -# def create_temp_mqtt_user(username_hint: str, ttl_seconds: int = 3600) -> dict: -# """ -# Legt einen temporären Mosquitto-Client (User) an via Dynamic Security API. -# Rückgabe: { "tempUser": "...", "tempPass": "...", "expires_at": epoch_sec } -# """ -# temp_user = f"sess_{secrets.token_hex(6)}" -# temp_pass = secrets.token_urlsafe(12) -# payload = { -# "username": temp_user, -# "password": temp_pass, -# "roles": [MOSQ_ROLE] -# } -# url = f"{MOSQUITTO_API}/client" -# try: -# r = requests.post(url, auth=(MOSQ_ADMIN_USER, MOSQ_ADMIN_PASS), json=payload, timeout=5) -# except Exception as e: -# raise RuntimeError(f"Mosquitto API nicht erreichbar: {e}") -# if r.status_code not in (200, 201): -# raise RuntimeError(f"Mosquitto-API Fehler ({r.status_code}): {r.text}") -# expires_at = int(time.time()) + ttl_seconds -# return {"tempUser": temp_user, "tempPass": temp_pass, "expires_at": expires_at} - - -# def delete_mqtt_user(username: str): -# url = f"{MOSQUITTO_API}/client/{username}" -# try: -# r = requests.delete(url, auth=(MOSQ_ADMIN_USER, MOSQ_ADMIN_PASS), timeout=5) -# return r.status_code in (200, 204) -# except Exception: -# return False - - -# ---------------------- -# Routes: Auth-Plugin kompatible Endpoints -# ---------------------- -# @app.post("/auth") -# def auth_check(): -# """ -# Erwartet form-encoded oder JSON: -# - username -# - password -# Antwort: -# - 200 OK -> erlaubt -# - 401/403 -> abgelehnt -# """ -# data = request.form.to_dict() or request.get_json(silent=True) or {} -# email = data.get("username", "") -# password = data.get("password", "") - -# # klassische Nutzer/Passwort-Prüfung -# if verify_user_password(email, password): -# return ("OK", 200) - -# return ("Unauthorized", 401) - - -# @app.post("/acl") -# def acl_check(): -# """ -# Erwartet (form oder json): -# - username -# - topic -# - acc (1=sub, 2=pub; je nach Plugin) -# - clientid (optional) -# Antwort: -# - 200 OK -> erlaubt -# - 403 -> verweigert -# """ -# data = request.form.to_dict() or request.get_json(silent=True) or {} -# email = data.get("username", "") -# topic = data.get("topic", "") -# acc = int(data.get("acc", 0)) - -# row = get_user(email) -# if not row or row["disabled"]: -# return ("Forbidden", 403) - -# role = row["role"] -# # Beispiel-ACLs — bitte an deine Anforderungen anpassen: -# if role == "admin": -# return ("OK", 200) -# if role == "viewer" and acc == 1: -# # nur lesen, zusätzlich Topic-Filter möglich -# if topic.startswith("sensors/") or topic.startswith("status/"): -# return ("OK", 200) -# if role == "operator": -# # operator darf lesen und schreiben auf device-Tops -# if topic.startswith("devices/") or topic.startswith("commands/"): -# return ("OK", 200) -# # Standard: verweigern -# return ("Forbidden", 403) +def create_temp_mqtt_user(username_hint: str, ttl_seconds: int = 3600) -> dict: + """Creates a temporary MQTT user via Mosquitto Dynamic Security API. + The user will have the role defined in MOSQ_ROLE. + The user will expire after ttl_seconds. + Returns: { "tempUser": "...", "tempPass": "...", "expires_at": epoch_sec } + """ + temp_user = f"sess_{token_hex(6)}" + temp_pass = token_urlsafe(12) + payload = { + "username": temp_user, + "password": temp_pass, + "roles": [MOSQ_ROLE] + } + url = f"{MOSQUITTO_API}/client" + try: + result = requests.post(url, auth=(MOSQ_ADMIN_USER, MOSQ_ADMIN_PASS), json=payload, timeout=5) + except Exception as e: + raise RuntimeError(f"Unable to connect to Mosquitto API: {e}") + if result.status_code not in (200, 201): + raise RuntimeError(f"Mosquitto-API Error ({result.status_code}): {result.text}") + expires_at = int(time()) + ttl_seconds + return {"tempUser": temp_user, "tempPass": temp_pass, "expires_at": expires_at} + + +def delete_mqtt_user(username: str): + """Deletes a MQTT user via Mosquitto Dynamic Security API. + Returns True on success, False otherwise. + """ + url = f"{MOSQUITTO_API}/client/{username}" + try: + result = requests.delete(url, auth=(MOSQ_ADMIN_USER, MOSQ_ADMIN_PASS), timeout=5) + return result.status_code in (200, 204) + except Exception: + return False # ---------------------- @@ -207,31 +264,37 @@ def set_cookie(resp: Response, key: str, value, expires: Optional[Union[str, dat @app.post("/api/login") -def web_login() -> Response: +def login() -> Response: data: dict = request.get_json(force=True) - email: Optional[str] = data.get("email") + username: Optional[str] = data.get("username") password: Optional[str] = data.get("password") - if email is None or password is None: - return jsonify(error="email/password required"), 400 - if not verify_user_password(email, password): + if username is None or password is None: + return jsonify(error="username/password required"), 400 + user_valid, actual_username = verify_user_password(username, password) + if not user_valid: return jsonify(error="invalid credentials"), 401 response = make_response(jsonify(success=True)) - # Cookie setzen - set_cookie(response, COOKIE_NAME, f"{email}:{password}", expires=None) + # set Cookie + set_cookie(response, COOKIE_NAME, f"{actual_username}:{password}", expires=None) + print_debug(f"User '{actual_username}' logged in.") return response @app.post("/api/logout") def logout() -> Response: + if debug: + username, _ = get_authenticated_username() # just for logging resp = make_response(jsonify(success=True)) - # Cookie löschen + # delete Cookie set_cookie(resp, COOKIE_NAME, "", expires=0) + print_debug(f"User '{username}' logged out.") return resp @app.get("/api/health") def health() -> Response: + print_debug("Health check") return jsonify(status="ok") @@ -245,13 +308,14 @@ def health() -> Response: # ---------------------- @app.get("/user/me") def user_me() -> Response: - email, err = get_authenticated_email() - if err: - return err - row = get_user(email) + username, error = get_authenticated_username() + if error: + return error + row = get_user(username) if not row or row["disabled"]: return jsonify(error="user not found"), 404 user_info = { + "username": row["username"], "email": row["email"], "first_name": row["first_name"], "last_name": row["last_name"], @@ -260,6 +324,7 @@ def user_me() -> Response: "created_at": db_timestamp_to_epoch_seconds(row["created_at"]), "token_expires_at": db_timestamp_to_epoch_seconds(row["password_token_expires_at"]) } + print_debug(f"User-Me for '{username}'") return jsonify(user=user_info) @@ -271,32 +336,62 @@ def user_update_password() -> Response: data: dict = request.get_json(force=True) old_password = data.get("old_password") new_password = data.get("new_password") - email = data.get("email") - token_used = False if old_password is None or new_password is None: return jsonify(error="old_password and new_password required"), 400 - # check for passwort token - if not verify_user_token(email, old_password): - email, err = get_authenticated_email() - if err: - return err - if not verify_user_password(email, old_password): - return jsonify(error="invalid old_password or token"), 401 - else: - token_used = True + username, error = get_authenticated_username() + if error: + return error + user_valid, _ = verify_user_password(username, old_password) + if not user_valid: + return jsonify(error="invalid old_password"), 401 pw_hash = bcrypt.hash(new_password) db_connection = db_connect() db_connection.execute( "UPDATE users SET password_hash = ?, password_token_hash = NULL, password_token_expires_at = NULL " - "WHERE email = ?", - (pw_hash, email) + "WHERE username = ?", + (pw_hash, username) ) db_connection.commit() db_connection.close() - response = make_response(jsonify(success=True, token_used=token_used)) - # Cookie setzen - set_cookie(response, COOKIE_NAME, f"{email}:{new_password}", expires=None) + response = make_response(jsonify(success=True)) + # set Cookie + set_cookie(response, COOKIE_NAME, f"{username}:{new_password}", expires=None) + print_debug(f"User '{username}' updated password.") + return response + + +# ---------------------- +# User-Reset-Password Endpoint +# ---------------------- +@app.post("/user/reset_password") +def user_reset_password() -> Response: + data: dict = request.get_json(force=True) + email = data.get("email") + new_password = data.get("new_password") + token = data.get("token") + if email is None or new_password is None or token is None: + return jsonify(error="email, new_password and token required"), 400 + row = get_user_by_email(email) + if not row: + return jsonify(error="invalid email or token"), 401 + username = row["username"] + if not verify_user_token(username, token): + return jsonify(error="invalid email or token"), 401 + pw_hash = bcrypt.hash(new_password) + db_connection = db_connect() + db_connection.execute( + "UPDATE users SET password_hash = ?, password_token_hash = NULL, password_token_expires_at = NULL " + "WHERE username = ?", + (pw_hash, username) + ) + db_connection.commit() + db_connection.close() + + response = make_response(jsonify(success=True)) + # set Cookie + set_cookie(response, COOKIE_NAME, f"{username}:{new_password}", expires=None) + print_debug(f"User '{username}' reset password via token.") return response @@ -327,7 +422,7 @@ def user_generate_token() -> Response: if affected_rows == 0: print(f"Password token requested for unknown email: {email}") # report success even if email not found to avoid user enumeration - sleep(randrange(5, 25) * 0.1) # künstliche Verzögerung + sleep(randrange(5, 25) * 0.1) # artificial delay to mitigate user enumeration return jsonify(success=True,) # send token to user via email gateway @@ -371,7 +466,7 @@ def user_generate_token() -> Response: # ---------------------- @app.post("/user/update") def user_update() -> Response: - email, error = get_authenticated_email() + username, error = get_authenticated_username() if error: return error data: dict = request.get_json(force=True) @@ -381,28 +476,30 @@ def user_update() -> Response: db_connection = db_connect() db_connection.execute( "UPDATE users SET first_name = ?, last_name = ?, comment = ? " - "WHERE email = ?", - (first_name, last_name, comment, email) + "WHERE username = ?", + (first_name, last_name, comment, username) ) db_connection.commit() db_connection.close() return jsonify(success=True) + # ---------------------- # Admin Endpoints # ---------------------- # ---------------------- -# User-Create Endpoint +# Admin Create-User Endpoint # ---------------------- @app.post("/admin/create_user") def admin_create_user() -> Response: - # Auth prüfen - _, error = get_authenticated_email(required_role="admin") + # validate Auth + _, error = get_authenticated_username(required_role="admin") if error: return error data: dict = request.get_json(force=True) + username = data.get("username") email = data.get("email") password = data.get("password") first_name = data.get("first_name") @@ -415,28 +512,29 @@ def admin_create_user() -> Response: db_connection = db_connect() try: db_connection.execute( - "INSERT INTO users (email, password_hash, first_name, last_name, role, disabled, comment) " - "VALUES (?, ?, ?, ?, ?, 0, ?)", - (email, pw_hash, first_name, last_name, role, comment) + "INSERT INTO users (username, email, password_hash, first_name, last_name, role, disabled, comment) " + "VALUES (?, ?, ?, ?, ?, ?, 0, ?)", + (username, email, pw_hash, first_name, last_name, role, comment) ) db_connection.commit() except sqlite3.IntegrityError: - return jsonify(error=f"user with email '{email}' already exists"), 409 + return jsonify(error=f"user '{username}' already exists"), 409 finally: db_connection.close() return jsonify(success=True, email=email) # ---------------------- -# User-Update Endpoint +# Admin Update-User Endpoint # ---------------------- @app.post("/admin/update_user") def admin_update_user() -> Response: - # Auth prüfen - _, err = get_authenticated_email(required_role="admin") - if err: - return err + # validate Auth + _, error = get_authenticated_username(required_role="admin") + if error: + return error data: dict = request.get_json(force=True) + username = data.get("username") email = data.get("email") first_name = data.get("first_name") last_name = data.get("last_name") @@ -448,85 +546,85 @@ def admin_update_user() -> Response: db_connection = db_connect() try: db_connection.execute( - "UPDATE users SET first_name = ?, last_name = ?, role = ?, disabled = ?, comment = ? " - "WHERE email = ?", - (first_name, last_name, role, disabled, comment, email) + "UPDATE users SET email = ?, first_name = ?, last_name = ?, role = ?, disabled = ?, comment = ? " + "WHERE username = ?", + (email, first_name, last_name, role, disabled, comment, username) ) db_connection.commit() except sqlite3.IntegrityError: return jsonify(error=f"user with email '{email}' already exists"), 409 finally: db_connection.close() - return jsonify(success=True, email=email) + return jsonify(success=True, username=username) # ---------------------- -# User-Delete Endpoint +# Admin Delete-User Endpoint # ---------------------- @app.post("/admin/delete_user") def admin_delete_user() -> Response: - # Auth prüfen - _, error = get_authenticated_email(required_role="admin") + # validate Auth + _, error = get_authenticated_username(required_role="admin") if error: return error data: dict = request.get_json(force=True) - email = data.get("email") - if not email: + username = data.get("username") + if not username: return jsonify(error="email required"), 400 db_connection = db_connect() db_cursor = db_connection.execute( - "DELETE FROM users WHERE email = ?", - (email,) + "DELETE FROM users WHERE username = ?", + (username,) ) deleted_rows = db_cursor.rowcount db_connection.commit() db_connection.close() if deleted_rows == 0: return jsonify(error="user not found"), 404 - return jsonify(success=True, email=email) + return jsonify(success=True, username=username) # ---------------------- -# User-Password Endpoint +# Admin Update-Password Endpoint # ---------------------- @app.post("/admin/update_password") def admin_update_password() -> Response: - # Auth prüfen - _, error = get_authenticated_email(required_role="admin") + # validate Auth + _, error = get_authenticated_username(required_role="admin") if error: return error data: dict = request.get_json(force=True) - email = data.get("email") + username = data.get("username") password = data.get("password") - if not email or not password: - return jsonify(error="email and password required"), 400 + if not username or not password: + return jsonify(error="username and password required"), 400 pw_hash = bcrypt.hash(password) db_connection = db_connect() db_cursor = db_connection.execute( "UPDATE users SET password_hash = ? " - "WHERE email = ?", - (pw_hash, email) + "WHERE username = ?", + (pw_hash, username) ) modified_rows = db_cursor.rowcount db_connection.commit() db_connection.close() if modified_rows == 0: - return jsonify(error=f"user with email '{email}' not found"), 409 + return jsonify(error=f"user '{username}' not found"), 409 return jsonify(success=True) # ---------------------- -# Get-Users Endpoint +# Admin Get-Users Endpoint # ---------------------- @app.get("/admin/get_users") def admin_get_users() -> Response: - # Auth prüfen - _, error = get_authenticated_email(required_role="admin") + # validate Auth + _, error = get_authenticated_username(required_role="admin") if error: return error db_connection = db_connect() db_cursor = db_connection.execute( - "SELECT email, first_name, last_name, comment, role, disabled, created_at " + "SELECT username, email, first_name, last_name, comment, role, disabled, created_at " "FROM users" ) users = [dict(row) for row in db_cursor.fetchall()] @@ -540,12 +638,16 @@ def admin_get_users() -> Response: # Start App # ---------------------- if __name__ == "__main__": - # Hinweis: Für Prod: WSGI-Server wie gunicorn + HTTPS-Frontend (z. B. nginx) verwenden - host = os.environ.get("LISTEN_HOST", "127.0.0.1") - port = int(os.environ.get("LISTEN_PORT", "3000")) - debug = os.environ.get("AUTH_DEBUG", "0") == "1" + if not os.path.exists(DB_PATH): + print(f"Datenbank nicht gefunden: {DB_PATH}") + print("Es wird eine neue Datenbank angelegt.") + init_db() + elif check_default_admin_user_exists(): + print("Warnung: Der initiale Admin-Benutzer mit Standard-Passwort existiert noch!") + print(f"Bitte ändere das Passwort des Benutzers '{DEFAULT_ADMIN_USER['username']}'!") + # IMPORTANT: For Production use: WSGI-Server like gunicorn + HTTPS-Frontend (eg. nginx) print(f"Starting Auth-Service on {host}:{port} (Debug={debug})") - # Starte mit waitress, falls verfügbar; sonst Fallback auf Flask-Dev-Server + # run with waitress, if present; fallback to Flask-Dev-Server try: from waitress import serve if debug: diff --git a/packages/auth_service/demo_token_client.py b/packages/auth_service/demo_token_client.py deleted file mode 100644 index c8c1a9246f..0000000000 --- a/packages/auth_service/demo_token_client.py +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/env python3 -""" -Einfacher Token-Client für das Forgot-Password-System. -Sendet E-Mail und Token an den Server. -""" - -import argparse -import json -import sys - -try: - import requests -except ImportError: - print("Bitte zuerst installieren: pip install requests", file=sys.stderr) - sys.exit(2) - - -def main(): - parser = argparse.ArgumentParser( - description="Token-Client: sendet E-Mail und Token an den Server.", - formatter_class=argparse.RawDescriptionHelpFormatter, - epilog=""" -Beispiele: - python3 token_client.py --email user@example.com --token "mein-geheimes-token" - python3 token_client.py -e user@example.com -t "token123" --debug - python3 token_client.py -e user@example.com -t "token123" --url https://openwb.de/forgotpassword/send_token.php - """ - ) - - parser.add_argument("-e", "--email", required=True, help="E-Mail-Adresse") - parser.add_argument("-t", "--token", required=True, help="Token zum Übertragen") - parser.add_argument("--url", default="https://openwb.de/forgotpassword/send_token.php", - help="Server-URL (Default: https://openwb.de/forgotpassword/send_token.php)") - parser.add_argument("--timeout", type=int, default=15, - help="HTTP-Timeout in Sekunden (Default: 15)") - parser.add_argument("--debug", action="store_true", - help="Debug-Ausgaben aktivieren") - - args = parser.parse_args() - - # Validierung - if "@" not in args.email: - print("Fehler: Ungültige E-Mail-Adresse", file=sys.stderr) - sys.exit(1) - - if not args.token.strip(): - print("Fehler: Token darf nicht leer sein", file=sys.stderr) - sys.exit(1) - - payload = { - "email": args.email, - "token": args.token, - } - - if args.debug: - print(f"DEBUG: URL: {args.url}") - print(f"DEBUG: Payload: {json.dumps(payload, indent=2)}") - print(f"DEBUG: Timeout: {args.timeout}s") - print("DEBUG: Sende Request...") - - try: - headers = { - 'Content-Type': 'application/json', - 'User-Agent': 'Token-Client/1.0' - } - - resp = requests.post( - args.url, - json=payload, - headers=headers, - timeout=args.timeout - ) - - except requests.exceptions.Timeout: - print(f"Fehler: Timeout nach {args.timeout} Sekunden", file=sys.stderr) - sys.exit(1) - except requests.exceptions.ConnectionError: - print(f"Fehler: Kann keine Verbindung zu {args.url} herstellen", file=sys.stderr) - sys.exit(1) - except requests.RequestException as e: - print(f"HTTP-Fehler: {e}", file=sys.stderr) - sys.exit(1) - - # Response anzeigen - print(f"✓ POST {args.url}") - print(f"✓ Status: {resp.status_code}") - - if args.debug: - print(f"DEBUG: Response Headers: {dict(resp.headers)}") - - # Content anzeigen - content_type = resp.headers.get("Content-Type", "").lower() - if "application/json" in content_type: - try: - data = resp.json() - print("Response:") - print(json.dumps(data, ensure_ascii=False, indent=2)) - - # Status auswerten - if resp.status_code == 200 and data.get('ok'): - print("\n✓ Erfolgreich! Prüfen Sie Ihr E-Mail-Postfach.") - elif data.get('error'): - print(f"\n✗ Fehler: {data['error']}", file=sys.stderr) - sys.exit(1) - - except json.JSONDecodeError: - print("Response (kein gültiges JSON):") - print(resp.text) - else: - print("Response:") - print(resp.text) - - if resp.status_code >= 400: - sys.exit(1) - - -if __name__ == "__main__": - main() diff --git a/packages/auth_service/init_db.py b/packages/auth_service/init_db.py deleted file mode 100644 index a6e1b403ca..0000000000 --- a/packages/auth_service/init_db.py +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env python3 -# init_db.py -import sqlite3 -from passlib.hash import bcrypt -import os -import getpass - -DB_PATH = os.environ.get("AUTH_DB", "./auth.db") - - -def init_db(): - db_connection = sqlite3.connect(DB_PATH) - db_cursor = db_connection.cursor() - # Alle TIMESTAMP-Spalten werden als UTC gespeichert! - db_cursor.executescript(""" - CREATE TABLE IF NOT EXISTS users ( - email TEXT PRIMARY KEY, - password_hash TEXT NOT NULL, - first_name TEXT, - last_name TEXT, - role TEXT NOT NULL DEFAULT 'viewer', - disabled INTEGER NOT NULL DEFAULT 0, - comment TEXT, - password_token_hash TEXT, - password_token_expires_at TIMESTAMP, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP - ); - """) - db_connection.commit() - db_connection.close() - print("DB initialisiert:", DB_PATH) - - -def create_user(email, password, first_name=None, last_name=None, role="viewer", comment=None): - db_connection = sqlite3.connect(DB_PATH) - db_cursor = db_connection.cursor() - pw_hash = bcrypt.hash(password) - db_cursor.execute( - "INSERT OR REPLACE INTO users (email, password_hash, first_name, last_name, role, disabled, comment) " - "VALUES (?, ?, ?, ?, ?, 0, ?);", - (email, pw_hash, first_name, last_name, role, comment) - ) - db_connection.commit() - db_connection.close() - print(f"Benutzer '{username}' angelegt (Rolle={role})") - - -if __name__ == "__main__": - init_db() - username = input("Admin-E-Mail [admin@localhost]: ") or "admin@localhost" - password = getpass.getpass("Passwort: ") - password_2 = getpass.getpass("Passwort wiederholen: ") - if password != password_2: - print("Passwörter stimmen nicht überein.") - raise SystemExit(1) - create_user(username, password, role="admin", comment="Initialer Admin-Benutzer") - print("Datenbankinitialisierung abgeschlossen.") diff --git a/packages/auth_service/requirements.txt b/packages/auth_service/requirements.txt deleted file mode 100644 index 3d5abc57aa..0000000000 --- a/packages/auth_service/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -Flask==3.1.2 -passlib==1.7.4 -Requests==2.32.5 -waitress==3.0.2 diff --git a/requirements.txt b/requirements.txt index 50a82e8a72..9d2e79002c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -25,3 +25,6 @@ ocpp==1.0.0 websockets==12.0 pycarwings3==0.7.14 asyncio==3.4.3 +Flask==3.1.2 +passlib==1.7.4 +waitress==3.0.2 From edeabdd3a4cc21a19f80a3a776a3460bfa0a9166 Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Tue, 18 Nov 2025 12:55:12 +0100 Subject: [PATCH 17/76] service installation --- auth.db | Bin 12288 -> 0 bytes data/config/openwbAuthServer.service | 13 +++++++++++++ openwb-install.sh | 8 +++++++- runs/atreboot.sh | 11 +++++++++++ 4 files changed, 31 insertions(+), 1 deletion(-) delete mode 100644 auth.db create mode 100644 data/config/openwbAuthServer.service diff --git a/auth.db b/auth.db deleted file mode 100644 index 8f0e07118accd244f57b6cedad573f3661a34874..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI$O;g%H7y#f+)M_0Sr!x-iZ4Wxuu>uKYTAXplh^wM}CZt{7~%CpF^v)@pB7`^khmnHB{}x_p$X6r0w4eaAOHd&00JNY0w4eaAn>;c ze0VC%#^Z6}V~pu7iv~XR{HPLh6{4sFtIA%1;HU{dpT~DWZQZo6O6n>;t>lYJrGZaK zls>C_q(^_N@W$7YK6jhP{;Iqra8JzqY>i{OaFbl=UTTz@h}5kW_x1lNt|hyS7aoHnEP;Q!w{}I)Cic=ylKZsIT#T zx0)}Ks;U%E@8$QX&ZzNI?`ZA0TBSltsy3PzF>Y*#kK#LV0hx|Lul>HoclMedFgLo^ zqBo*R(O0;yp9}v{i@b2eZP$=3oY)_}mV^uWs0; zvun9+-RinNySugAv>Ua0Ju4;K$M0_v@7@q5B?Fo=%95Q?+D9HcV3u@7_KfUBr}^r2 z{ Date: Fri, 21 Nov 2025 08:53:07 +0100 Subject: [PATCH 18/76] disable auth server --- data/config/apache/apache-openwb-ssl.conf | 26 +++++++++++------------ openwb-install.sh | 10 ++++----- requirements.txt | 6 +++--- runs/atreboot.sh | 20 ++++++++--------- 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/data/config/apache/apache-openwb-ssl.conf b/data/config/apache/apache-openwb-ssl.conf index a54c3af6c0..6ecbf4cc38 100644 --- a/data/config/apache/apache-openwb-ssl.conf +++ b/data/config/apache/apache-openwb-ssl.conf @@ -147,19 +147,19 @@ # ToDo: remove /mqtt target once all clients use /ws ProxyPassMatch "^/(ws|mqtt)(/|$)" "wss://127.0.0.1:9002/" - # Auth-Service-Proxy - - ProxyPass http://127.0.0.1:3000/ - ProxyPassReverse http://127.0.0.1:3000/ - - # Optional: Header durchreichen, falls Auth-Service sie braucht - RequestHeader set X-Forwarded-Proto "https" - RequestHeader set X-Forwarded-Port "443" - - # Sicherheit (keine Directory Listings etc.) - Options -Indexes - Require all granted - + # # Auth-Service-Proxy + # + # ProxyPass http://127.0.0.1:3000/ + # ProxyPassReverse http://127.0.0.1:3000/ + + # # Optional: Header durchreichen, falls Auth-Service sie braucht + # RequestHeader set X-Forwarded-Proto "https" + # RequestHeader set X-Forwarded-Port "443" + + # # Sicherheit (keine Directory Listings etc.) + # Options -Indexes + # Require all granted + # diff --git a/openwb-install.sh b/openwb-install.sh index 8de81ffe1d..b694b5eca1 100755 --- a/openwb-install.sh +++ b/openwb-install.sh @@ -123,10 +123,10 @@ ln -s "${OPENWBBASEDIR}/data/config/openwb2.service" /etc/systemd/system/openwb2 systemctl daemon-reload systemctl enable openwb2 -echo "installing openwb2 auth service..." -ln -s "${OPENWBBASEDIR}/data/config/openwbAuthServer.service" /etc/systemd/system/openwbAuthServer.service -systemctl daemon-reload -systemctl enable openwbAuthServer +# echo "installing openwb2 auth service..." +# ln -s "${OPENWBBASEDIR}/data/config/openwbAuthServer.service" /etc/systemd/system/openwbAuthServer.service +# systemctl daemon-reload +# systemctl enable openwbAuthServer echo "installing openwb2-simpleAPI service..." ln -s "${OPENWBBASEDIR}/data/config/openwb-simpleAPI.service" /etc/systemd/system/openwb-simpleAPI.service @@ -140,7 +140,7 @@ systemctl enable openwbRemoteSupport systemctl start openwbRemoteSupport echo "installation finished, now starting openwb services..." -systemctl start openwbAuthServer +# systemctl start openwbAuthServer systemctl start openwb2 echo "all done" diff --git a/requirements.txt b/requirements.txt index 9d2e79002c..2dd5745fbc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -25,6 +25,6 @@ ocpp==1.0.0 websockets==12.0 pycarwings3==0.7.14 asyncio==3.4.3 -Flask==3.1.2 -passlib==1.7.4 -waitress==3.0.2 +#Flask==3.1.2 +#passlib==1.7.4 +#waitress==3.0.2 diff --git a/runs/atreboot.sh b/runs/atreboot.sh index 1fee3d9460..07f92e79c2 100755 --- a/runs/atreboot.sh +++ b/runs/atreboot.sh @@ -189,16 +189,16 @@ chmod 666 "$LOGFILE" sudo reboot now & fi - # check for openwb Auth service definition - if find /etc/systemd/system/ -maxdepth 1 -name openwbAuthServer.service -type l | grep -q "."; then - echo "openwbAuthServer.service definition is already a symlink" - else - sudo ln -s "${OPENWBBASEDIR}/data/config/openwbAuthServer.service" /etc/systemd/system/openwbAuthServer.service - sudo systemctl daemon-reload - sudo systemctl enable openwbAuthServer - echo "openwbAuthServer.service definition updated. restarting service..." - sudo systemctl restart openwbAuthServer - fi + # # check for openwb Auth service definition + # if find /etc/systemd/system/ -maxdepth 1 -name openwbAuthServer.service -type l | grep -q "."; then + # echo "openwbAuthServer.service definition is already a symlink" + # else + # sudo ln -s "${OPENWBBASEDIR}/data/config/openwbAuthServer.service" /etc/systemd/system/openwbAuthServer.service + # sudo systemctl daemon-reload + # sudo systemctl enable openwbAuthServer + # echo "openwbAuthServer.service definition updated. restarting service..." + # sudo systemctl restart openwbAuthServer + # fi # check for openwb-simpleAPI service definition if find /etc/systemd/system/ -maxdepth 1 -name openwb-simpleAPI.service -type l | grep -q "."; then From e3f1c8fdfbe05d0116626d00a8a7f4ef1b10fa65 Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Fri, 21 Nov 2025 08:58:09 +0100 Subject: [PATCH 19/76] implement switching between acl and dynsec --- .../{ => local}/mosquitto_local.conf | 0 .../{ => local}/mosquitto_local_init | 0 .../mosquitto/{ => local}/openwb_local.conf | 0 .../mosquitto/{ => public}/mosquitto.acl | 0 .../mosquitto/{ => public}/mosquitto.conf | 0 data/config/mosquitto/public/mosquitto_ctrl | 6 ++ .../openwb-default-acl.conf} | 11 +-- .../openwb-unsecure-acl.conf} | 0 .../public/openwb-user-management.conf | 19 +++++ data/config/mosquitto/public/openwb.conf | 6 ++ openwb-install.sh | 15 ++-- packages/control/general.py | 4 +- packages/helpermodules/setdata.py | 3 +- packages/helpermodules/subdata.py | 20 +++++ packages/helpermodules/update_config.py | 4 +- runs/setup_mosquitto.sh | 81 ++++++++++++++----- 16 files changed, 128 insertions(+), 41 deletions(-) rename data/config/mosquitto/{ => local}/mosquitto_local.conf (100%) rename data/config/mosquitto/{ => local}/mosquitto_local_init (100%) rename data/config/mosquitto/{ => local}/openwb_local.conf (100%) rename data/config/mosquitto/{ => public}/mosquitto.acl (100%) rename data/config/mosquitto/{ => public}/mosquitto.conf (100%) create mode 100644 data/config/mosquitto/public/mosquitto_ctrl rename data/config/mosquitto/{openwb.conf => public/openwb-default-acl.conf} (53%) rename data/config/mosquitto/{openwb_insecure.conf => public/openwb-unsecure-acl.conf} (100%) create mode 100644 data/config/mosquitto/public/openwb-user-management.conf create mode 100644 data/config/mosquitto/public/openwb.conf diff --git a/data/config/mosquitto/mosquitto_local.conf b/data/config/mosquitto/local/mosquitto_local.conf similarity index 100% rename from data/config/mosquitto/mosquitto_local.conf rename to data/config/mosquitto/local/mosquitto_local.conf diff --git a/data/config/mosquitto/mosquitto_local_init b/data/config/mosquitto/local/mosquitto_local_init similarity index 100% rename from data/config/mosquitto/mosquitto_local_init rename to data/config/mosquitto/local/mosquitto_local_init diff --git a/data/config/mosquitto/openwb_local.conf b/data/config/mosquitto/local/openwb_local.conf similarity index 100% rename from data/config/mosquitto/openwb_local.conf rename to data/config/mosquitto/local/openwb_local.conf diff --git a/data/config/mosquitto/mosquitto.acl b/data/config/mosquitto/public/mosquitto.acl similarity index 100% rename from data/config/mosquitto/mosquitto.acl rename to data/config/mosquitto/public/mosquitto.acl diff --git a/data/config/mosquitto/mosquitto.conf b/data/config/mosquitto/public/mosquitto.conf similarity index 100% rename from data/config/mosquitto/mosquitto.conf rename to data/config/mosquitto/public/mosquitto.conf diff --git a/data/config/mosquitto/public/mosquitto_ctrl b/data/config/mosquitto/public/mosquitto_ctrl new file mode 100644 index 0000000000..bd50650ecc --- /dev/null +++ b/data/config/mosquitto/public/mosquitto_ctrl @@ -0,0 +1,6 @@ +-u admin +-P openwb +-h localhost +-p 8883 +--cafile /etc/mosquitto/certs/openwb.pem +--insecure diff --git a/data/config/mosquitto/openwb.conf b/data/config/mosquitto/public/openwb-default-acl.conf similarity index 53% rename from data/config/mosquitto/openwb.conf rename to data/config/mosquitto/public/openwb-default-acl.conf index 5290fe952c..f846a50771 100644 --- a/data/config/mosquitto/openwb.conf +++ b/data/config/mosquitto/public/openwb-default-acl.conf @@ -1,4 +1,4 @@ -# openwb-version:5 +# openwb-version:1 # public secure websocket listener listener 9002 @@ -7,13 +7,6 @@ allow_anonymous true certfile /etc/mosquitto/certs/openwb.pem keyfile /etc/mosquitto/certs/openwb.key acl_file /etc/mosquitto/mosquitto.acl -#plugin /usr/lib/x86_64-linux-gnu/mosquitto_dynamic_security.so -#plugin_opt_config_file /var/lib/mosquitto/dynamic_security.json - -# local bridge listener -listener 1884 localhost -protocol mqtt -allow_anonymous true # public secure mqtt listener listener 8883 @@ -22,5 +15,3 @@ allow_anonymous true certfile /etc/mosquitto/certs/openwb.pem keyfile /etc/mosquitto/certs/openwb.key acl_file /etc/mosquitto/mosquitto.acl -#plugin /usr/lib/x86_64-linux-gnu/mosquitto_dynamic_security.so -#plugin_opt_config_file /var/lib/mosquitto/dynamic_security.json diff --git a/data/config/mosquitto/openwb_insecure.conf b/data/config/mosquitto/public/openwb-unsecure-acl.conf similarity index 100% rename from data/config/mosquitto/openwb_insecure.conf rename to data/config/mosquitto/public/openwb-unsecure-acl.conf diff --git a/data/config/mosquitto/public/openwb-user-management.conf b/data/config/mosquitto/public/openwb-user-management.conf new file mode 100644 index 0000000000..e1dbe9d10e --- /dev/null +++ b/data/config/mosquitto/public/openwb-user-management.conf @@ -0,0 +1,19 @@ +# openwb-version:1 + +# public secure websocket listener +listener 9002 +protocol websockets +allow_anonymous true +certfile /etc/mosquitto/certs/openwb.pem +keyfile /etc/mosquitto/certs/openwb.key +plugin /usr/lib/x86_64-linux-gnu/mosquitto_dynamic_security.so +plugin_opt_config_file /var/lib/mosquitto/dynamic_security.json + +# public secure mqtt listener +listener 8883 +protocol mqtt +allow_anonymous true +certfile /etc/mosquitto/certs/openwb.pem +keyfile /etc/mosquitto/certs/openwb.key +plugin /usr/lib/x86_64-linux-gnu/mosquitto_dynamic_security.so +plugin_opt_config_file /var/lib/mosquitto/dynamic_security.json diff --git a/data/config/mosquitto/public/openwb.conf b/data/config/mosquitto/public/openwb.conf new file mode 100644 index 0000000000..105ea11082 --- /dev/null +++ b/data/config/mosquitto/public/openwb.conf @@ -0,0 +1,6 @@ +# openwb-version:5 + +# local bridge listener +listener 1884 localhost +protocol mqtt +allow_anonymous true diff --git a/openwb-install.sh b/openwb-install.sh index b694b5eca1..0c84743016 100755 --- a/openwb-install.sh +++ b/openwb-install.sh @@ -61,21 +61,22 @@ fi echo "updating mosquitto config file" systemctl stop mosquitto sleep 2 -cp -a "${OPENWBBASEDIR}/data/config/mosquitto/mosquitto.conf" /etc/mosquitto/mosquitto.conf -cp "${OPENWBBASEDIR}/data/config/mosquitto/openwb.conf" /etc/mosquitto/conf.d/openwb.conf -cp "${OPENWBBASEDIR}/data/config/mosquitto/openwb_insecure.conf" /etc/mosquitto/conf.d/openwb_insecure.conf.disabled -cp "${OPENWBBASEDIR}/data/config/mosquitto/mosquitto.acl" /etc/mosquitto/mosquitto.acl +SRC="${OPENWBBASEDIR}/data/config/mosquitto/public" +cp -a "${SRC}/mosquitto.conf" "${SRC}/mosquitto.acl" /etc/mosquitto/ +# enable default listeners: local bridge, public secure and unsecure mqtt and ws listeners with acl files +cp -a "${SRC}/openwb.conf" "${SRC}/openwb-unsecure-acl.conf" "${SRC}/openwb-default-acl.conf" /etc/mosquitto/conf.d/ sudo cp /etc/ssl/certs/ssl-cert-snakeoil.pem /etc/mosquitto/certs/openwb.pem sudo cp /etc/ssl/private/ssl-cert-snakeoil.key /etc/mosquitto/certs/openwb.key sudo chgrp mosquitto /etc/mosquitto/certs/openwb.key systemctl start mosquitto #check for mosquitto_local instance +SRC="${OPENWBBASEDIR}/data/config/mosquitto/local" if [ ! -f /etc/init.d/mosquitto_local ]; then echo "setting up mosquitto local instance" install -d -m 0755 -o root -g root /etc/mosquitto/conf_local.d/ install -d -m 0755 -o mosquitto -g root /var/lib/mosquitto_local - cp "${OPENWBBASEDIR}/data/config/mosquitto/mosquitto_local_init" /etc/init.d/mosquitto_local + cp "${SRC}/mosquitto_local_init" /etc/init.d/mosquitto_local chown root:root /etc/init.d/mosquitto_local chmod 755 /etc/init.d/mosquitto_local systemctl daemon-reload @@ -84,8 +85,8 @@ else systemctl stop mosquitto_local sleep 2 fi -cp -a "${OPENWBBASEDIR}/data/config/mosquitto/mosquitto_local.conf" /etc/mosquitto/mosquitto_local.conf -cp -a "${OPENWBBASEDIR}/data/config/mosquitto/openwb_local.conf" /etc/mosquitto/conf_local.d/ +cp -a "${SRC}/mosquitto_local.conf" /etc/mosquitto/ +cp -a "${SRC}/openwb_local.conf" /etc/mosquitto/conf_local.d/ systemctl start mosquitto_local echo "mosquitto done" diff --git a/packages/control/general.py b/packages/control/general.py index 8bbed5aac3..686e8440bd 100644 --- a/packages/control/general.py +++ b/packages/control/general.py @@ -100,7 +100,9 @@ class GeneralData: http_api: bool = field( default=False, metadata={"topic": "http_api"}) allow_unencrypted_access: bool = field( - default=False, metadata={"topic": "allow_unencrypted_access"}) + default=True, metadata={"topic": "allow_unencrypted_access"}) + user_management_active: bool = field( + default=False, metadata={"topic": "user_management_active"}) mqtt_bridge: bool = False temporary_charge_templates_active: bool = False prices: Prices = field(default_factory=prices_factory) diff --git a/packages/helpermodules/setdata.py b/packages/helpermodules/setdata.py index 2f75a77c2e..6faa73388b 100644 --- a/packages/helpermodules/setdata.py +++ b/packages/helpermodules/setdata.py @@ -726,7 +726,8 @@ def process_general_topic(self, msg: mqtt.MQTTMessage): elif ("openWB/set/general/http_api" in msg.topic or "openWB/set/general/modbus_control" in msg.topic or "openWB/set/general/extern" in msg.topic or - "openWB/set/general/allow_unencrypted_access" in msg.topic): + "openWB/set/general/allow_unencrypted_access" in msg.topic or + "openWB/set/general/user_management_active" in msg.topic): self._validate_value(msg, bool) elif "openWB/set/general/control_interval" in msg.topic: self._validate_value(msg, int, [(10, 10), (20, 20), (60, 60)]) diff --git a/packages/helpermodules/subdata.py b/packages/helpermodules/subdata.py index 9f8c66a9b7..e6b894a652 100644 --- a/packages/helpermodules/subdata.py +++ b/packages/helpermodules/subdata.py @@ -649,6 +649,26 @@ def process_general_topic(self, var: general.General, msg: mqtt.MQTTMessage): MessageType.WARNING ) self.set_json_payload_class(var.data, msg) + elif "openWB/general/user_management_active" == msg.topic: + user_management_active = decode_payload(msg.payload) + if ( + self.event_subdata_initialized.is_set() and + self.general_data.data.user_management_active != user_management_active + ): + log.warning("Änderung der Einstellung 'user_management_active' erkannt.") + run_command([ + str(Path(__file__).resolve().parents[2] / "runs" / "setup_mosquitto.sh"), + "0" # kein Neustart im laufenden Betrieb! + ], process_exception=True) + log.warning("Mosquitto-Konfiguration wurde angepasst.") + pub_system_message( + msg.payload, + f"Benutzerverwaltung wurde {'' if user_management_active else 'de'}aktiviert.
" + "Bitte die openWB " + "neu starten, damit die Änderungen wirksam werden.", + MessageType.SUCCESS + ) + self.set_json_payload_class(var.data, msg) else: self.set_json_payload_class(var.data, msg) except Exception: diff --git a/packages/helpermodules/update_config.py b/packages/helpermodules/update_config.py index a319a6650f..54fbf7120e 100644 --- a/packages/helpermodules/update_config.py +++ b/packages/helpermodules/update_config.py @@ -201,6 +201,7 @@ class UpdateConfig: "^openWB/counter/[0-9]+/config/max_total_power$", "^openWB/general/allow_unencrypted_access$", + "^openWB/general/user_management_active$", "^openWB/general/extern$", "^openWB/general/extern_display_mode$", "^openWB/general/charge_log_data_config$", @@ -533,7 +534,8 @@ class UpdateConfig: ("openWB/vehicle/template/ev_template/0", asdict(EvTemplateData(name="Standard-Fahrzeug-Profil", min_current=10))), ("openWB/vehicle/template/charge_template/0", get_charge_template_default()), - ("openWB/general/allow_unencrypted_access", False), + ("openWB/general/allow_unencrypted_access", True), + ("openWB/general/user_management_active", False), ("openWB/general/charge_log_data_config", get_default_charge_log_columns()), ("openWB/general/chargemode_config/pv_charging/bat_mode", BatConsiderationMode.EV_MODE.value), ("openWB/general/chargemode_config/pv_charging/bat_power_discharge", 1000), diff --git a/runs/setup_mosquitto.sh b/runs/setup_mosquitto.sh index 830fae155c..9cfbb1e333 100755 --- a/runs/setup_mosquitto.sh +++ b/runs/setup_mosquitto.sh @@ -1,6 +1,7 @@ #!/bin/bash OPENWBBASEDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) automaticServiceRestart=${1:-0} +resetDynamicSecurity=${2:-0} versionMatch() { file=$1 @@ -41,50 +42,87 @@ waitForServiceStop() { # check for mosquitto configuration echo "check mosquitto installation..." restartService=0 +SRC="${OPENWBBASEDIR}/data/config/mosquitto/public" echo "mosquitto main configuration..." -if versionMatch "${OPENWBBASEDIR}/data/config/mosquitto/mosquitto.conf" "/etc/mosquitto/mosquitto.conf"; then +if versionMatch "${SRC}/mosquitto.conf" "/etc/mosquitto/mosquitto.conf"; then echo "mosquitto.conf already up to date" else echo "updating mosquitto.conf" - sudo cp "${OPENWBBASEDIR}/data/config/mosquitto/mosquitto.conf" "/etc/mosquitto/mosquitto.conf" + sudo cp "${SRC}/mosquitto.conf" "/etc/mosquitto/mosquitto.conf" restartService=1 fi echo "mosquitto openwb configuration..." -if versionMatch "${OPENWBBASEDIR}/data/config/mosquitto/openwb.conf" "/etc/mosquitto/conf.d/openwb.conf"; then +if versionMatch "${SRC}/openwb.conf" "/etc/mosquitto/conf.d/openwb.conf"; then echo "mosquitto openwb.conf already up to date" else echo "updating mosquitto openwb.conf" - sudo cp "${OPENWBBASEDIR}/data/config/mosquitto/openwb.conf" "/etc/mosquitto/conf.d/openwb.conf" + sudo cp "${SRC}/openwb.conf" "/etc/mosquitto/conf.d/openwb.conf" restartService=1 fi -allowUnencryptedAccess=$(mosquitto_sub -t "openWB/general/allow_unencrypted_access" -p 1886 -C 1 -W 1 --quiet) +userManagementActive=$(mosquitto_sub -t "openWB/general/user_management_active" -p 1886 -C 1 -W 1 --quiet) +if [[ $userManagementActive == "true" ]]; then + echo "mosquitto user management enabled, disabling unencrypted access" + allowUnencryptedAccess="false" + if versionMatch "${SRC}/openwb-user-management.conf" "/etc/mosquitto/conf.d/openwb-user-management.conf"; then + echo "mosquitto openwb-user-management.conf already up to date" + else + echo "updating mosquitto openwb-user-management.conf" + sudo cp "${SRC}/openwb-user-management.conf" "/etc/mosquitto/conf.d/openwb-user-management.conf" + restartService=1 + fi + if [ -f "/var/lib/mosquitto/dynamic_security.json" ] && ((resetDynamicSecurity == 0)); then + echo "dynamic security configuration found, no action needed" + else + echo "creating initial dynamic security configuration with default user 'admin' and password 'openwb'" + sudo mosquitto_ctrl dynsec init /var/lib/mosquitto/dynamic_security.json admin openwb + sudo chown mosquitto:mosquitto /var/lib/mosquitto/dynamic_security.json + cp "${SRC}/mosquitto_ctrl" /home/openwb/.config/mosquitto_ctrl + restartService=1 + fi + if [ -f "/etc/mosquitto/conf.d/openwb-default-acl.conf" ]; then + echo "removing mosquitto openwb-default-acl.conf" + sudo rm "/etc/mosquitto/conf.d/openwb-default-acl.conf" + restartService=1 + else + echo "mosquitto openwb-default-acl.conf not present, no action needed" + fi + if [ -f "/etc/mosquitto/conf.d/openwb-unsecure.conf" ]; then + echo "removing mosquitto openwb-unsecure.conf" + sudo rm "/etc/mosquitto/conf.d/openwb-unsecure.conf" + restartService=1 + else + echo "mosquitto openwb-unsecure.conf not present, no action needed" + fi +else + allowUnencryptedAccess=$(mosquitto_sub -t "openWB/general/allow_unencrypted_access" -p 1886 -C 1 -W 1 --quiet) +fi if [[ $allowUnencryptedAccess == "true" ]]; then - if versionMatch "${OPENWBBASEDIR}/data/config/mosquitto/openwb_insecure.conf" "/etc/mosquitto/conf.d/openwb_insecure.conf"; then - echo "mosquitto openwb_insecure.conf already up to date" + if versionMatch "${SRC}/openwb-unsecure.conf" "/etc/mosquitto/conf.d/openwb-unsecure.conf"; then + echo "mosquitto openwb-unsecure.conf already up to date" else - echo "updating mosquitto openwb_insecure.conf" - sudo cp "${OPENWBBASEDIR}/data/config/mosquitto/openwb_insecure.conf" "/etc/mosquitto/conf.d/openwb_insecure.conf" + echo "updating mosquitto openwb-unsecure.conf" + sudo cp "${SRC}/openwb-unsecure.conf" "/etc/mosquitto/conf.d/openwb-unsecure.conf" restartService=1 fi else - if [ -f "/etc/mosquitto/conf.d/openwb_insecure.conf" ]; then - echo "removing mosquitto openwb_insecure.conf" - sudo rm "/etc/mosquitto/conf.d/openwb_insecure.conf" + if [ -f "/etc/mosquitto/conf.d/openwb-unsecure.conf" ]; then + echo "removing mosquitto openwb-unsecure.conf" + sudo rm "/etc/mosquitto/conf.d/openwb-unsecure.conf" restartService=1 else - echo "mosquitto openwb_insecure.conf not present, no action needed" + echo "mosquitto openwb-unsecure.conf not present, no action needed" fi fi echo "mosquitto acl configuration..." -if versionMatch "${OPENWBBASEDIR}/data/config/mosquitto/mosquitto.acl" "/etc/mosquitto/mosquitto.acl"; then +if versionMatch "${SRC}/mosquitto.acl" "/etc/mosquitto/mosquitto.acl"; then echo "mosquitto acl already up to date" else echo "updating mosquitto acl" - sudo cp "${OPENWBBASEDIR}/data/config/mosquitto/mosquitto.acl" "/etc/mosquitto/mosquitto.acl" + sudo cp "${SRC}/mosquitto.acl" "/etc/mosquitto/mosquitto.acl" restartService=1 fi @@ -106,30 +144,31 @@ fi #check for mosquitto_local instance # restartService=0 # if we restart mosquitto, we need to restart mosquitto_local as well +SRC="${OPENWBBASEDIR}/data/config/mosquitto/local" echo "mosquitto_local instance..." -if versionMatch "${OPENWBBASEDIR}/data/config/mosquitto/mosquitto_local_init" "/etc/init.d/mosquitto_local"; then +if versionMatch "${SRC}/mosquitto_local_init" "/etc/init.d/mosquitto_local"; then echo "mosquitto_local service definition already up to date" else echo "updating mosquitto_local service definition" - sudo cp "${OPENWBBASEDIR}/data/config/mosquitto/mosquitto_local_init" /etc/init.d/mosquitto_local + sudo cp "${SRC}/mosquitto_local_init" /etc/init.d/mosquitto_local sudo chown root:root /etc/init.d/mosquitto_local sudo chmod 755 /etc/init.d/mosquitto_local sudo systemctl daemon-reload sudo systemctl enable mosquitto_local restartService=1 fi -if versionMatch "${OPENWBBASEDIR}/data/config/mosquitto/mosquitto_local.conf" "/etc/mosquitto/mosquitto_local.conf"; then +if versionMatch "${SRC}/mosquitto_local.conf" "/etc/mosquitto/mosquitto_local.conf"; then echo "mosquitto_local.conf already up to date" else echo "updating mosquitto_local.conf" - sudo cp -a "${OPENWBBASEDIR}/data/config/mosquitto/mosquitto_local.conf" "/etc/mosquitto/mosquitto_local.conf" + sudo cp -a "${SRC}/mosquitto_local.conf" "/etc/mosquitto/mosquitto_local.conf" restartService=1 fi -if versionMatch "${OPENWBBASEDIR}/data/config/mosquitto/openwb_local.conf" "/etc/mosquitto/conf_local.d/openwb_local.conf"; then +if versionMatch "${SRC}/openwb_local.conf" "/etc/mosquitto/conf_local.d/openwb_local.conf"; then echo "mosquitto openwb_local.conf already up to date" else echo "updating mosquitto openwb_local.conf" - sudo cp -a "${OPENWBBASEDIR}/data/config/mosquitto/openwb_local.conf" "/etc/mosquitto/conf_local.d/" + sudo cp -a "${SRC}/openwb_local.conf" "/etc/mosquitto/conf_local.d/" restartService=1 fi if ((restartService == 1 && automaticServiceRestart == 1)); then From 259e50dfbaf6584480f146b61d208c30c9242403 Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Mon, 24 Nov 2025 07:52:09 +0100 Subject: [PATCH 20/76] fix mosquitto setup --- .../mosquitto/local/mosquitto_local.conf | 2 -- data/config/mosquitto/public/mosquitto.conf | 2 -- data/config/mosquitto/public/openwb.conf | 2 +- runs/setup_mosquitto.sh | 34 ++++++++++++------- 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/data/config/mosquitto/local/mosquitto_local.conf b/data/config/mosquitto/local/mosquitto_local.conf index 7036c45c36..f8ef1c226f 100644 --- a/data/config/mosquitto/local/mosquitto_local.conf +++ b/data/config/mosquitto/local/mosquitto_local.conf @@ -5,8 +5,6 @@ persistence_location /var/lib/mosquitto_local/ log_type error log_type warning log_dest file /var/log/mosquitto/mosquitto_local.log -# timestamp format currently not supported in stretch or buster with mosquitto 1.5 -# only enable on bullseye and newer log_timestamp_format %Y-%m-%dT%H:%M:%S include_dir /etc/mosquitto/conf_local.d diff --git a/data/config/mosquitto/public/mosquitto.conf b/data/config/mosquitto/public/mosquitto.conf index 0c98e4d2b4..6359c5770b 100644 --- a/data/config/mosquitto/public/mosquitto.conf +++ b/data/config/mosquitto/public/mosquitto.conf @@ -4,8 +4,6 @@ persistence_location /var/lib/mosquitto/ log_type error log_type warning log_dest file /var/log/mosquitto/mosquitto.log -# timestamp format currently not supported in stretch or buster with mosquitto 1.5 -# only enable on bullseye and newer log_timestamp_format %Y-%m-%dT%H:%M:%S # required to restrict access per listener diff --git a/data/config/mosquitto/public/openwb.conf b/data/config/mosquitto/public/openwb.conf index 105ea11082..5ee0df4296 100644 --- a/data/config/mosquitto/public/openwb.conf +++ b/data/config/mosquitto/public/openwb.conf @@ -1,4 +1,4 @@ -# openwb-version:5 +# openwb-version:4 # local bridge listener listener 1884 localhost diff --git a/runs/setup_mosquitto.sh b/runs/setup_mosquitto.sh index 9cfbb1e333..e2b15ccf6c 100755 --- a/runs/setup_mosquitto.sh +++ b/runs/setup_mosquitto.sh @@ -63,6 +63,8 @@ else fi userManagementActive=$(mosquitto_sub -t "openWB/general/user_management_active" -p 1886 -C 1 -W 1 --quiet) +allowUnencryptedAccess=$(mosquitto_sub -t "openWB/general/allow_unencrypted_access" -p 1886 -C 1 -W 1 --quiet) +echo "mosquitto settings: user_management_active=$userManagementActive, allow_unencrypted_access=$allowUnencryptedAccess" if [[ $userManagementActive == "true" ]]; then echo "mosquitto user management enabled, disabling unencrypted access" allowUnencryptedAccess="false" @@ -89,31 +91,37 @@ if [[ $userManagementActive == "true" ]]; then else echo "mosquitto openwb-default-acl.conf not present, no action needed" fi - if [ -f "/etc/mosquitto/conf.d/openwb-unsecure.conf" ]; then - echo "removing mosquitto openwb-unsecure.conf" - sudo rm "/etc/mosquitto/conf.d/openwb-unsecure.conf" + if [ -f "/etc/mosquitto/conf.d/openwb-unsecure-acl.conf" ]; then + echo "removing mosquitto openwb-unsecure-acl.conf" + sudo rm "/etc/mosquitto/conf.d/openwb-unsecure-acl.conf" restartService=1 else - echo "mosquitto openwb-unsecure.conf not present, no action needed" + echo "mosquitto openwb-unsecure-acl.conf not present, no action needed" fi else - allowUnencryptedAccess=$(mosquitto_sub -t "openWB/general/allow_unencrypted_access" -p 1886 -C 1 -W 1 --quiet) + if versionMatch "${SRC}/openwb-default-acl.conf" "/etc/mosquitto/conf.d/openwb-default-acl.conf"; then + echo "mosquitto openwb-default-acl.conf already up to date" + else + echo "updating mosquitto openwb-default-acl.conf" + sudo cp "${SRC}/openwb-default-acl.conf" "/etc/mosquitto/conf.d/openwb-default-acl.conf" + restartService=1 + fi fi if [[ $allowUnencryptedAccess == "true" ]]; then - if versionMatch "${SRC}/openwb-unsecure.conf" "/etc/mosquitto/conf.d/openwb-unsecure.conf"; then - echo "mosquitto openwb-unsecure.conf already up to date" + if versionMatch "${SRC}/openwb-unsecure-acl.conf" "/etc/mosquitto/conf.d/openwb-unsecure-acl.conf"; then + echo "mosquitto openwb-unsecure-acl.conf already up to date" else - echo "updating mosquitto openwb-unsecure.conf" - sudo cp "${SRC}/openwb-unsecure.conf" "/etc/mosquitto/conf.d/openwb-unsecure.conf" + echo "updating mosquitto openwb-unsecure-acl.conf" + sudo cp "${SRC}/openwb-unsecure-acl.conf" "/etc/mosquitto/conf.d/openwb-unsecure-acl.conf" restartService=1 fi else - if [ -f "/etc/mosquitto/conf.d/openwb-unsecure.conf" ]; then - echo "removing mosquitto openwb-unsecure.conf" - sudo rm "/etc/mosquitto/conf.d/openwb-unsecure.conf" + if [ -f "/etc/mosquitto/conf.d/openwb-unsecure-acl.conf" ]; then + echo "removing mosquitto openwb-unsecure-acl.conf" + sudo rm "/etc/mosquitto/conf.d/openwb-unsecure-acl.conf" restartService=1 else - echo "mosquitto openwb-unsecure.conf not present, no action needed" + echo "mosquitto openwb-unsecure-acl.conf not present, no action needed" fi fi From a17c6b061f20a93e40f2a36d8f26b67bdc2fd0c5 Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Mon, 24 Nov 2025 08:03:48 +0100 Subject: [PATCH 21/76] fix apache setup --- runs/setup_apache2.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/runs/setup_apache2.sh b/runs/setup_apache2.sh index 961eacb6f2..4d8805f050 100755 --- a/runs/setup_apache2.sh +++ b/runs/setup_apache2.sh @@ -72,9 +72,7 @@ disableSite() { # check apache modules echo "checking required apache modules..." enableModule headers -enableModule rewrite enableModule ssl -enableModule proxy_http enableModule proxy_wstunnel # default site (http and https) @@ -100,11 +98,13 @@ allowUnencryptedAccess=$(mosquitto_sub -t "openWB/general/allow_unencrypted_acce if [[ $allowUnencryptedAccess == "true" ]]; then echo "WARNING: unencrypted access is enabled!" disableSite apache-redirect-ssl + disableModule rewrite enableSite 000-default else echo "unencrypted access is disabled" disableSite 000-default enableSite apache-redirect-ssl + enableModule rewrite fi # enable http api ssl site if configured @@ -123,10 +123,12 @@ if lsusb | grep -q 'RTL8153'; then echo "second network for pro plus detected" # enable pro+ specific configurations enableSite apache-proplus + enableModule proxy_http else echo "no second network for pro plus detected" # disable all pro+ specific configurations disableSite apache-proplus + disableModule proxy_http fi # restart apache if required From 1097fee858f9806d21472dcd11b6f6659291d1d2 Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Mon, 24 Nov 2025 08:36:26 +0100 Subject: [PATCH 22/76] fix file comparison --- runs/atreboot.sh | 2 +- runs/setup_apache2.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/runs/atreboot.sh b/runs/atreboot.sh index 07f92e79c2..03ada7627a 100755 --- a/runs/atreboot.sh +++ b/runs/atreboot.sh @@ -12,7 +12,7 @@ chmod 666 "$LOGFILE" file=$1 target=$2 currentVersion=$(grep -o "openwb-version:[0-9]\+" "$file" | grep -o "[0-9]\+$") - installedVersion=$(grep -o "openwb-version:[0-9]\+" "$target" | grep -o "[0-9]\+$") + installedVersion=$(sudo grep -o "openwb-version:[0-9]\+" "$target" | grep -o "[0-9]\+$") # echo "$currentVersion == $installedVersion ?" if ((currentVersion == installedVersion)); then return 0 diff --git a/runs/setup_apache2.sh b/runs/setup_apache2.sh index 4d8805f050..04415b7922 100755 --- a/runs/setup_apache2.sh +++ b/runs/setup_apache2.sh @@ -6,7 +6,7 @@ versionMatch() { file=$1 target=$2 currentVersion=$(grep -o "openwb-version:[0-9]\+" "$file" | grep -o "[0-9]\+$") - installedVersion=$(grep -o "openwb-version:[0-9]\+" "$target" | grep -o "[0-9]\+$") + installedVersion=$(sudo grep -o "openwb-version:[0-9]\+" "$target" | grep -o "[0-9]\+$") if ((currentVersion == installedVersion)); then return 0 else From 8958cffe0167c73bef49e3c2a2ef115109bcece8 Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Mon, 24 Nov 2025 11:25:17 +0100 Subject: [PATCH 23/76] fix dynsec setup --- .../public/default-dynamic-security.json | 118 ++++++++++++++++++ .../public/openwb-user-management.conf | 4 +- packages/helpermodules/subdata.py | 4 - runs/setup_mosquitto.sh | 8 +- 4 files changed, 124 insertions(+), 10 deletions(-) create mode 100644 data/config/mosquitto/public/default-dynamic-security.json diff --git a/data/config/mosquitto/public/default-dynamic-security.json b/data/config/mosquitto/public/default-dynamic-security.json new file mode 100644 index 0000000000..3085a16331 --- /dev/null +++ b/data/config/mosquitto/public/default-dynamic-security.json @@ -0,0 +1,118 @@ +{ + "defaultACLAccess": { + "publishClientSend": false, + "publishClientReceive": true, + "subscribe": false, + "unsubscribe": true + }, + "clients": [{ + "username": "admin", + "textname": "Administrator", + "roles": [{ + "rolename": "dynsec_admin" + }, { + "rolename": "full_access" + }], + "password": "Yamo/Sa9TbMaYSGBPtJCglEuGFrY5CWQrToXwqUhRPOkcepwUoMgoFqaFpkhoKxpEc+Q5KofojN61BZrB9DBQQ==", + "salt": "dExADR+vHv85IcDI", + "iterations": 101 + }], + "groups": [{ + "groupname": "anonymous", + "textname": "Anonyme Benutzer", + "roles": [{ + "rolename": "full_access" + }], + "clients": [] + }], + "anonymousGroup": "anonymous", + "roles": [{ + "rolename": "dynsec_admin", + "textname": "Dynamic Security Administrator", + "acls": [{ + "acltype": "publishClientSend", + "topic": "$CONTROL/dynamic-security/#", + "priority": 0, + "allow": true + }, { + "acltype": "publishClientReceive", + "topic": "$CONTROL/dynamic-security/#", + "priority": 0, + "allow": true + }, { + "acltype": "publishClientReceive", + "topic": "$SYS/#", + "priority": 0, + "allow": true + }, { + "acltype": "publishClientReceive", + "topic": "#", + "priority": 0, + "allow": true + }, { + "acltype": "subscribePattern", + "topic": "$CONTROL/dynamic-security/#", + "priority": 0, + "allow": true + }, { + "acltype": "subscribePattern", + "topic": "$SYS/#", + "priority": 0, + "allow": true + }, { + "acltype": "subscribePattern", + "topic": "#", + "priority": 0, + "allow": true + }, { + "acltype": "unsubscribePattern", + "topic": "#", + "priority": 0, + "allow": true + }] + }, { + "rolename": "full_access", + "textname": "Voller Zugriff", + "acls": [{ + "acltype": "publishClientSend", + "topic": "openWB/set/#", + "priority": 0, + "allow": true + }, { + "acltype": "publishClientSend", + "topic": "openWB/system/messages/#", + "priority": 0, + "allow": true + }, { + "acltype": "publishClientSend", + "topic": "openWB/command/+/messages/#", + "priority": 0, + "allow": true + }, { + "acltype": "publishClientSend", + "topic": "others/#", + "priority": 0, + "allow": true + }, { + "acltype": "publishClientSend", + "topic": "openWB/simpleAPI/set/#", + "priority": 0, + "allow": true + }, { + "acltype": "subscribePattern", + "topic": "openWB/#", + "priority": 0, + "allow": true + }, { + "acltype": "subscribePattern", + "topic": "openWB-remote/#", + "priority": 0, + "allow": true + }, { + "acltype": "subscribePattern", + "topic": "others/#", + "priority": 0, + "allow": true + }] + }] +} diff --git a/data/config/mosquitto/public/openwb-user-management.conf b/data/config/mosquitto/public/openwb-user-management.conf index e1dbe9d10e..e6d968045e 100644 --- a/data/config/mosquitto/public/openwb-user-management.conf +++ b/data/config/mosquitto/public/openwb-user-management.conf @@ -7,7 +7,7 @@ allow_anonymous true certfile /etc/mosquitto/certs/openwb.pem keyfile /etc/mosquitto/certs/openwb.key plugin /usr/lib/x86_64-linux-gnu/mosquitto_dynamic_security.so -plugin_opt_config_file /var/lib/mosquitto/dynamic_security.json +plugin_opt_config_file /var/lib/mosquitto/dynamic-security.json # public secure mqtt listener listener 8883 @@ -16,4 +16,4 @@ allow_anonymous true certfile /etc/mosquitto/certs/openwb.pem keyfile /etc/mosquitto/certs/openwb.key plugin /usr/lib/x86_64-linux-gnu/mosquitto_dynamic_security.so -plugin_opt_config_file /var/lib/mosquitto/dynamic_security.json +plugin_opt_config_file /var/lib/mosquitto/dynamic-security.json diff --git a/packages/helpermodules/subdata.py b/packages/helpermodules/subdata.py index e6b894a652..9cbac44856 100644 --- a/packages/helpermodules/subdata.py +++ b/packages/helpermodules/subdata.py @@ -623,10 +623,6 @@ def process_general_topic(self, var: general.General, msg: mqtt.MQTTMessage): self.set_json_payload_class(var.data, msg) elif "openWB/general/allow_unencrypted_access" == msg.topic: allow_unencrypted_access = decode_payload(msg.payload) - log.warning(f"Topic: 'allow_unencrypted_access' Payload: {allow_unencrypted_access}") - log.warning(f"Aktuelle Einstellung: {self.general_data.data.allow_unencrypted_access}") - log.warning("Event subdata_initialized: " - f"{self.event_subdata_initialized.is_set()}") if ( self.event_subdata_initialized.is_set() and self.general_data.data.allow_unencrypted_access != allow_unencrypted_access diff --git a/runs/setup_mosquitto.sh b/runs/setup_mosquitto.sh index e2b15ccf6c..f10a7f3f7d 100755 --- a/runs/setup_mosquitto.sh +++ b/runs/setup_mosquitto.sh @@ -75,12 +75,12 @@ if [[ $userManagementActive == "true" ]]; then sudo cp "${SRC}/openwb-user-management.conf" "/etc/mosquitto/conf.d/openwb-user-management.conf" restartService=1 fi - if [ -f "/var/lib/mosquitto/dynamic_security.json" ] && ((resetDynamicSecurity == 0)); then - echo "dynamic security configuration found, no action needed" + if [ -f "/var/lib/mosquitto/dynamic-security.json" ] && ((resetDynamicSecurity == 0)); then + echo "dynamic security configuration found an reset not forced, no action needed" else echo "creating initial dynamic security configuration with default user 'admin' and password 'openwb'" - sudo mosquitto_ctrl dynsec init /var/lib/mosquitto/dynamic_security.json admin openwb - sudo chown mosquitto:mosquitto /var/lib/mosquitto/dynamic_security.json + sudo cp "${SRC}/default-dynamic-security.json" /var/lib/mosquitto/dynamic-security.json + sudo chown mosquitto:mosquitto /var/lib/mosquitto/dynamic-security.json cp "${SRC}/mosquitto_ctrl" /home/openwb/.config/mosquitto_ctrl restartService=1 fi From 06872d1a2ed54fc7e4ff135c3650859b97889972 Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Mon, 24 Nov 2025 11:30:14 +0100 Subject: [PATCH 24/76] migrate simpleAPI to localhost 1884 --- data/config/mosquitto/public/mosquitto.acl | 5 +++-- data/config/simpleAPI_mqtt_config.json | 4 ++-- simpleAPI/config/config.php | 2 +- simpleAPI/src/MqttClient.php | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/data/config/mosquitto/public/mosquitto.acl b/data/config/mosquitto/public/mosquitto.acl index 18221aa66e..b754bfbf30 100644 --- a/data/config/mosquitto/public/mosquitto.acl +++ b/data/config/mosquitto/public/mosquitto.acl @@ -1,4 +1,4 @@ -# openwb-version:3 +# openwb-version:4 # allow publishing set topics topic write openWB/set/# # allow clearing system messages @@ -12,4 +12,5 @@ topic read openWB-remote/# # allow brach "others" for devices other than openWB topic readwrite others/# # allow read write access for simpleAPI -topic readwrite openWB/simpleAPI/# +topic read openWB/simpleAPI/# +topic readwrite openWB/simpleAPI/set/# diff --git a/data/config/simpleAPI_mqtt_config.json b/data/config/simpleAPI_mqtt_config.json index d1b06a2844..5010dc36f7 100644 --- a/data/config/simpleAPI_mqtt_config.json +++ b/data/config/simpleAPI_mqtt_config.json @@ -1,9 +1,9 @@ { "host": "localhost", - "port": 8883, + "port": 1884, "username": null, "password": null, - "use_tls": true, + "use_tls": false, "validate_cert": false, "qos": 0, "retain": true, diff --git a/simpleAPI/config/config.php b/simpleAPI/config/config.php index 0a0ee92c58..619e73e11d 100644 --- a/simpleAPI/config/config.php +++ b/simpleAPI/config/config.php @@ -4,7 +4,7 @@ // MQTT Broker Konfiguration 'mqtt' => [ 'server' => 'localhost', - 'port' => 8883, + 'port' => 1884, 'validate_cert' => false, 'username' => '', 'password' => '', diff --git a/simpleAPI/src/MqttClient.php b/simpleAPI/src/MqttClient.php index 22c1f3d2d7..4e2e896042 100644 --- a/simpleAPI/src/MqttClient.php +++ b/simpleAPI/src/MqttClient.php @@ -21,7 +21,7 @@ class MqttClient public function __construct($config) { $this->server = $config['mqtt']['server'] ?? 'localhost'; - $this->port = $config['mqtt']['port'] ?? 8883; + $this->port = $config['mqtt']['port'] ?? 1884; $this->validate_cert = $config['mqtt']['validate_cert'] ?? false; $this->username = $config['mqtt']['username'] ?? ''; $this->password = $config['mqtt']['password'] ?? ''; From 2ae382bb550e4046c27f3bb71ae40423b262166d Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Tue, 25 Nov 2025 07:59:54 +0100 Subject: [PATCH 25/76] add official mosquitto apt repository --- runs/install_packages.sh | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/runs/install_packages.sh b/runs/install_packages.sh index fa764c4b60..7cf859f723 100755 --- a/runs/install_packages.sh +++ b/runs/install_packages.sh @@ -1,4 +1,15 @@ #!/bin/bash +echo "add required repositories..." +# add mosquitto repository +if [ ! -f /etc/apt/sources.list.d/mosquitto.list ]; then + sudo apt-get -q -y install wget apt-transport-https + sudo wget -q https://repo.mosquitto.org/debian/mosquitto-repo.gpg -O /etc/apt/trusted.gpg.d/mosquitto-repo.gpg + # get installed debian version + . /etc/os-release + sudo wget -q -O /etc/apt/sources.list.d/mosquitto.list "https://repo.mosquitto.org/debian/mosquitto-${VERSION_CODENAME}.list" +fi +echo "done" + echo "install required packages with 'apt-get'..." sudo apt-get -q update sudo apt-get -q -y install \ From eb10290329f5ec954737d6541df8928fff737eb5 Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Tue, 25 Nov 2025 08:28:55 +0100 Subject: [PATCH 26/76] configuration changes on boot only --- packages/helpermodules/subdata.py | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/packages/helpermodules/subdata.py b/packages/helpermodules/subdata.py index 9cbac44856..23f2789985 100644 --- a/packages/helpermodules/subdata.py +++ b/packages/helpermodules/subdata.py @@ -627,16 +627,8 @@ def process_general_topic(self, var: general.General, msg: mqtt.MQTTMessage): self.event_subdata_initialized.is_set() and self.general_data.data.allow_unencrypted_access != allow_unencrypted_access ): - log.warning("Änderung der Einstellung 'allow_unencrypted_access' erkannt.") - run_command([ - str(Path(__file__).resolve().parents[2] / "runs" / "setup_apache2.sh") - ], process_exception=True) - log.warning("Apache2-Konfiguration wurde angepasst.") - run_command([ - str(Path(__file__).resolve().parents[2] / "runs" / "setup_mosquitto.sh"), - "0" # kein Neustart im laufenden Betrieb! - ], process_exception=True) - log.warning("Mosquitto-Konfiguration wurde angepasst.") + log.warning("Änderung der Einstellung 'allow_unencrypted_access' erkannt. " + "Konfiguration von Apache2 und Mosquitto wird beim nächsten Neustart angepasst.") pub_system_message( msg.payload, f"Unsichere Verbindungen wurden {'' if allow_unencrypted_access else 'de'}aktiviert.
" @@ -651,18 +643,14 @@ def process_general_topic(self, var: general.General, msg: mqtt.MQTTMessage): self.event_subdata_initialized.is_set() and self.general_data.data.user_management_active != user_management_active ): - log.warning("Änderung der Einstellung 'user_management_active' erkannt.") - run_command([ - str(Path(__file__).resolve().parents[2] / "runs" / "setup_mosquitto.sh"), - "0" # kein Neustart im laufenden Betrieb! - ], process_exception=True) - log.warning("Mosquitto-Konfiguration wurde angepasst.") + log.warning("Änderung der Einstellung 'user_management_active' erkannt. " + "Konfiguration von Mosquitto wird beim nächsten Neustart angepasst.") pub_system_message( msg.payload, f"Benutzerverwaltung wurde {'' if user_management_active else 'de'}aktiviert.
" "Bitte die openWB " "neu starten, damit die Änderungen wirksam werden.", - MessageType.SUCCESS + MessageType.WARNING ) self.set_json_payload_class(var.data, msg) else: From 3a4cf0e1b55547e06639ec0db431f925463dd43e Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Mon, 1 Dec 2025 12:42:19 +0100 Subject: [PATCH 27/76] fix mosquitto.acl ownership --- openwb-install.sh | 1 + runs/setup_mosquitto.sh | 1 + 2 files changed, 2 insertions(+) diff --git a/openwb-install.sh b/openwb-install.sh index 0c84743016..e094fc4e55 100755 --- a/openwb-install.sh +++ b/openwb-install.sh @@ -63,6 +63,7 @@ systemctl stop mosquitto sleep 2 SRC="${OPENWBBASEDIR}/data/config/mosquitto/public" cp -a "${SRC}/mosquitto.conf" "${SRC}/mosquitto.acl" /etc/mosquitto/ +sudo chown mosquitto:mosquitto /etc/mosquitto/mosquitto.acl # enable default listeners: local bridge, public secure and unsecure mqtt and ws listeners with acl files cp -a "${SRC}/openwb.conf" "${SRC}/openwb-unsecure-acl.conf" "${SRC}/openwb-default-acl.conf" /etc/mosquitto/conf.d/ sudo cp /etc/ssl/certs/ssl-cert-snakeoil.pem /etc/mosquitto/certs/openwb.pem diff --git a/runs/setup_mosquitto.sh b/runs/setup_mosquitto.sh index f10a7f3f7d..04f59b9029 100755 --- a/runs/setup_mosquitto.sh +++ b/runs/setup_mosquitto.sh @@ -131,6 +131,7 @@ if versionMatch "${SRC}/mosquitto.acl" "/etc/mosquitto/mosquitto.acl"; then else echo "updating mosquitto acl" sudo cp "${SRC}/mosquitto.acl" "/etc/mosquitto/mosquitto.acl" + sudo chown mosquitto:mosquitto "/etc/mosquitto/mosquitto.acl" restartService=1 fi From 1b99e781b94107182fc7a9e6395768468a309412 Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Tue, 2 Dec 2025 07:27:41 +0100 Subject: [PATCH 28/76] fix disabling user management --- runs/setup_mosquitto.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/runs/setup_mosquitto.sh b/runs/setup_mosquitto.sh index 04f59b9029..7df3cde8d4 100755 --- a/runs/setup_mosquitto.sh +++ b/runs/setup_mosquitto.sh @@ -99,6 +99,10 @@ if [[ $userManagementActive == "true" ]]; then echo "mosquitto openwb-unsecure-acl.conf not present, no action needed" fi else + if [ -f "/etc/mosquitto/conf.d/openwb-user-management.conf" ]; then + sudo rm "/etc/mosquitto/conf.d/openwb-user-management.conf" + restartService=1 + fi if versionMatch "${SRC}/openwb-default-acl.conf" "/etc/mosquitto/conf.d/openwb-default-acl.conf"; then echo "mosquitto openwb-default-acl.conf already up to date" else From 5885e2ef01c9d15d2d887293f20d83259137485e Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Thu, 4 Dec 2025 13:15:53 +0100 Subject: [PATCH 29/76] add resetUserManagement command --- packages/helpermodules/command.py | 8 ++++++++ runs/reset_user_management.sh | 11 +++++++++++ runs/setup_mosquitto.sh | 5 ++--- 3 files changed, 21 insertions(+), 3 deletions(-) create mode 100755 runs/reset_user_management.sh diff --git a/packages/helpermodules/command.py b/packages/helpermodules/command.py index 345d8bc8d0..d40b9b7e6e 100644 --- a/packages/helpermodules/command.py +++ b/packages/helpermodules/command.py @@ -953,6 +953,14 @@ def removeCloudBridge(self, connection_id: str, payload: dict): } }) + def resetUserManagement(self, connection_id: str, payload: dict) -> None: + log.info("User management reset requested!") + parent_file = Path(__file__).resolve().parents[2] + run_command([str(parent_file / "runs" / "reset_user_management.sh")]) + pub_user_message(payload, connection_id, + "Benutzerverwaltung wurde zurückgesetzt.", + MessageType.WARNING) + class ErrorHandlingContext: def __init__(self, payload: dict, connection_id: str): diff --git a/runs/reset_user_management.sh b/runs/reset_user_management.sh new file mode 100755 index 0000000000..a91cf531e6 --- /dev/null +++ b/runs/reset_user_management.sh @@ -0,0 +1,11 @@ +#!/bin/bash +{ + echo "Resetting user management..." + FILE="/var/lib/mosquitto/dynamic-security.json" + if [ -f $FILE ]; then + sudo rm /var/lib/mosquitto/dynamic-security.json + echo "Dynamic security file removed." + else + echo "No dynamic security file found." + fi +} >> /var/www/html/openWB/ramdisk/reset_user_management.log 2>&1 diff --git a/runs/setup_mosquitto.sh b/runs/setup_mosquitto.sh index 7df3cde8d4..3d19d489ba 100755 --- a/runs/setup_mosquitto.sh +++ b/runs/setup_mosquitto.sh @@ -1,7 +1,6 @@ #!/bin/bash OPENWBBASEDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) automaticServiceRestart=${1:-0} -resetDynamicSecurity=${2:-0} versionMatch() { file=$1 @@ -75,8 +74,8 @@ if [[ $userManagementActive == "true" ]]; then sudo cp "${SRC}/openwb-user-management.conf" "/etc/mosquitto/conf.d/openwb-user-management.conf" restartService=1 fi - if [ -f "/var/lib/mosquitto/dynamic-security.json" ] && ((resetDynamicSecurity == 0)); then - echo "dynamic security configuration found an reset not forced, no action needed" + if [ -f "/var/lib/mosquitto/dynamic-security.json" ]; then + echo "dynamic security configuration found, no action needed" else echo "creating initial dynamic security configuration with default user 'admin' and password 'openwb'" sudo cp "${SRC}/default-dynamic-security.json" /var/lib/mosquitto/dynamic-security.json From 6c2670915db7700ae05464a45e473f635b5a8972 Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Mon, 8 Dec 2025 07:46:31 +0100 Subject: [PATCH 30/76] upgrade npm packages --- .../cards/source/package-lock.json | 2914 ++++++++--------- .../display_themes/cards/source/package.json | 40 +- .../source/src/components/DashboardCard.vue | 4 +- .../display_themes/cards/source/src/main.scss | 4 +- .../cards/source/vite.config.js | 3 +- 5 files changed, 1470 insertions(+), 1495 deletions(-) diff --git a/packages/modules/display_themes/cards/source/package-lock.json b/packages/modules/display_themes/cards/source/package-lock.json index 72bf1f1d83..07c0a0bcf2 100644 --- a/packages/modules/display_themes/cards/source/package-lock.json +++ b/packages/modules/display_themes/cards/source/package-lock.json @@ -8,57 +8,85 @@ "name": "openwb-display-cards", "version": "0.0.0", "dependencies": { - "@fortawesome/fontawesome-svg-core": "^7.0.0", - "@fortawesome/free-regular-svg-icons": "^7.0.0", - "@fortawesome/free-solid-svg-icons": "^7.0.0", - "@fortawesome/vue-fontawesome": "^3.1.1", + "@fortawesome/fontawesome-svg-core": "^7.1.0", + "@fortawesome/free-regular-svg-icons": "^7.1.0", + "@fortawesome/free-solid-svg-icons": "^7.1.0", + "@fortawesome/vue-fontawesome": "^3.1.2", "@inkline/inkline": "^3.2.2", "buffer": "^6.0.3", - "chart.js": "^4.5.0", + "chart.js": "^4.5.1", "chartjs-adapter-luxon": "^1.3.1", "chartjs-plugin-annotation": "^3.1.0", "events": "^3.3.0", - "luxon": "^3.7.1", - "mqtt": "^5.14.0", + "luxon": "^3.7.2", + "mqtt": "^5.14.1", "node-stdlib-browser": "^1.3.1", - "pinia": "^3.0.3", + "pinia": "^3.0.4", "vue": "^3.5.18", - "vue-chartjs": "^5.3.2", - "vue-router": "^4.5.1" + "vue-chartjs": "^5.3.3", + "vue-router": "^4.6.3" }, "devDependencies": { "@rollup/plugin-terser": "^0.4.4", - "@rushstack/eslint-patch": "^1.12.0", - "@vitejs/plugin-vue": "^6.0.1", + "@rushstack/eslint-patch": "^1.15.0", + "@vitejs/plugin-vue": "^6.0.2", "@vue/eslint-config-prettier": "^10.2.0", "@vue/test-utils": "^2.4.6", - "eslint": "^9.33.0", - "eslint-plugin-vue": "^10.4.0", - "jsdom": "^26.1.0", + "eslint": "^9.39.1", + "eslint-plugin-vue": "^10.6.2", + "jsdom": "^27.2.0", "postcss": "^8.5.6", - "postcss-preset-env": "^10.2.4", - "prettier": "^3.6.2", + "postcss-preset-env": "^10.5.0", + "prettier": "^3.7.4", "rollup-plugin-polyfill-node": "^0.13.0", - "sass": "^1.90.0", - "vite": "^5.4.19", + "sass": "^1.94.2", + "vite": "^7.2.7", "vite-plugin-node-polyfills": "^0.24.0", - "vitest": "^3.2.4" + "vitest": "^4.0.15" } }, + "node_modules/@acemir/cssom": { + "version": "0.9.28", + "resolved": "https://registry.npmjs.org/@acemir/cssom/-/cssom-0.9.28.tgz", + "integrity": "sha512-LuS6IVEivI75vKN8S04qRD+YySP0RmU/cV8UNukhQZvprxF+76Z43TNo/a08eCodaGhT1Us8etqS1ZRY9/Or0A==", + "dev": true, + "license": "MIT" + }, "node_modules/@asamuzakjp/css-color": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz", - "integrity": "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-4.1.0.tgz", + "integrity": "sha512-9xiBAtLn4aNsa4mDnpovJvBn72tNEIACyvlqaNJ+ADemR+yeMJWnBudOi2qGDviJa7SwcDOU/TRh5dnET7qk0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@csstools/css-calc": "^2.1.4", + "@csstools/css-color-parser": "^3.1.0", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "lru-cache": "^11.2.2" + } + }, + "node_modules/@asamuzakjp/dom-selector": { + "version": "6.7.6", + "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-6.7.6.tgz", + "integrity": "sha512-hBaJER6A9MpdG3WgdlOolHmbOYvSk46y7IQN/1+iqiCuUu6iWdQrs9DGKF8ocqsEqWujWf/V7b7vaDgiUmIvUg==", "dev": true, "license": "MIT", "dependencies": { - "@csstools/css-calc": "^2.1.3", - "@csstools/css-color-parser": "^3.0.9", - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3", - "lru-cache": "^10.4.3" + "@asamuzakjp/nwsapi": "^2.3.9", + "bidi-js": "^1.0.3", + "css-tree": "^3.1.0", + "is-potential-custom-element-name": "^1.0.1", + "lru-cache": "^11.2.4" } }, + "node_modules/@asamuzakjp/nwsapi": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz", + "integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==", + "dev": true, + "license": "MIT" + }, "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", @@ -69,21 +97,21 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.3.tgz", - "integrity": "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", "license": "MIT", "dependencies": { - "@babel/types": "^7.28.2" + "@babel/types": "^7.28.5" }, "bin": { "parser": "bin/babel-parser.js" @@ -93,22 +121,22 @@ } }, "node_modules/@babel/runtime": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.3.tgz", - "integrity": "sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/types": { - "version": "7.28.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz", - "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" + "@babel/helper-validator-identifier": "^7.28.5" }, "engines": { "node": ">=6.9.0" @@ -139,9 +167,9 @@ } }, "node_modules/@csstools/color-helpers": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.2.tgz", - "integrity": "sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz", + "integrity": "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==", "dev": true, "funding": [ { @@ -183,9 +211,9 @@ } }, "node_modules/@csstools/css-color-parser": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.10.tgz", - "integrity": "sha512-TiJ5Ajr6WRd1r8HSiwJvZBiJOqtH86aHpUjq5aEKWHiII2Qfjqd/HCWKPOW8EP4vcspXbHnXrwIDlu5savQipg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz", + "integrity": "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==", "dev": true, "funding": [ { @@ -199,7 +227,7 @@ ], "license": "MIT", "dependencies": { - "@csstools/color-helpers": "^5.0.2", + "@csstools/color-helpers": "^5.1.0", "@csstools/css-calc": "^2.1.4" }, "engines": { @@ -233,6 +261,26 @@ "@csstools/css-tokenizer": "^3.0.4" } }, + "node_modules/@csstools/css-syntax-patches-for-csstree": { + "version": "1.0.20", + "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.0.20.tgz", + "integrity": "sha512-8BHsjXfSciZxjmHQOuVdW2b8WLUPts9a+mfL13/PzEviufUEW2xnvQuOlKs9dRBHgRqJ53SF/DUoK9+MZk72oQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + } + }, "node_modules/@csstools/css-tokenizer": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", @@ -277,6 +325,36 @@ "@csstools/css-tokenizer": "^3.0.4" } }, + "node_modules/@csstools/postcss-alpha-function": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-alpha-function/-/postcss-alpha-function-1.0.1.tgz", + "integrity": "sha512-isfLLwksH3yHkFXfCI2Gcaqg7wGGHZZwunoJzEZk0yKYIokgre6hYVFibKL3SYAoR1kBXova8LB+JoO5vZzi9w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.1.0", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, "node_modules/@csstools/postcss-cascade-layers": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-5.0.2.tgz", @@ -304,10 +382,10 @@ "postcss": "^8.4" } }, - "node_modules/@csstools/postcss-cascade-layers/node_modules/@csstools/selector-specificity": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", - "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", + "node_modules/@csstools/postcss-color-function": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-4.0.12.tgz", + "integrity": "sha512-yx3cljQKRaSBc2hfh8rMZFZzChaFgwmO2JfFgFr1vMcF3C/uyy5I4RFIBOIWGq1D+XbKCG789CGkG6zzkLpagA==", "dev": true, "funding": [ { @@ -320,31 +398,54 @@ } ], "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.1.0", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", + "@csstools/utilities": "^2.0.0" + }, "engines": { "node": ">=18" }, "peerDependencies": { - "postcss-selector-parser": "^7.0.0" + "postcss": "^8.4" } }, - "node_modules/@csstools/postcss-cascade-layers/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "node_modules/@csstools/postcss-color-function-display-p3-linear": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function-display-p3-linear/-/postcss-color-function-display-p3-linear-1.0.1.tgz", + "integrity": "sha512-E5qusdzhlmO1TztYzDIi8XPdPoYOjoTY6HBYBCYSj+Gn4gQRBlvjgPQXzfzuPQqt8EhkC/SzPKObg4Mbn8/xMg==", "dev": true, - "license": "MIT", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" + "@csstools/css-color-parser": "^3.1.0", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", + "@csstools/utilities": "^2.0.0" }, "engines": { - "node": ">=4" + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" } }, - "node_modules/@csstools/postcss-color-function": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-4.0.10.tgz", - "integrity": "sha512-4dY0NBu7NVIpzxZRgh/Q/0GPSz/jLSw0i/u3LTUor0BkQcz/fNhN10mSWBDsL0p9nDb0Ky1PD6/dcGbhACuFTQ==", + "node_modules/@csstools/postcss-color-mix-function": { + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-mix-function/-/postcss-color-mix-function-3.0.12.tgz", + "integrity": "sha512-4STERZfCP5Jcs13P1U5pTvI9SkgLgfMUMhdXW8IlJWkzOOOqhZIjcNhWtNJZes2nkBDsIKJ0CJtFtuaZ00moag==", "dev": true, "funding": [ { @@ -358,10 +459,10 @@ ], "license": "MIT-0", "dependencies": { - "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-color-parser": "^3.1.0", "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4", - "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -371,10 +472,10 @@ "postcss": "^8.4" } }, - "node_modules/@csstools/postcss-color-mix-function": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@csstools/postcss-color-mix-function/-/postcss-color-mix-function-3.0.10.tgz", - "integrity": "sha512-P0lIbQW9I4ShE7uBgZRib/lMTf9XMjJkFl/d6w4EMNHu2qvQ6zljJGEcBkw/NsBtq/6q3WrmgxSS8kHtPMkK4Q==", + "node_modules/@csstools/postcss-color-mix-variadic-function-arguments": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-mix-variadic-function-arguments/-/postcss-color-mix-variadic-function-arguments-1.0.2.tgz", + "integrity": "sha512-rM67Gp9lRAkTo+X31DUqMEq+iK+EFqsidfecmhrteErxJZb6tUoJBVQca1Vn1GpDql1s1rD1pKcuYzMsg7Z1KQ==", "dev": true, "funding": [ { @@ -388,10 +489,10 @@ ], "license": "MIT-0", "dependencies": { - "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-color-parser": "^3.1.0", "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4", - "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -401,10 +502,10 @@ "postcss": "^8.4" } }, - "node_modules/@csstools/postcss-color-mix-variadic-function-arguments": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-color-mix-variadic-function-arguments/-/postcss-color-mix-variadic-function-arguments-1.0.0.tgz", - "integrity": "sha512-Z5WhouTyD74dPFPrVE7KydgNS9VvnjB8qcdes9ARpCOItb4jTnm7cHp4FhxCRUoyhabD0WVv43wbkJ4p8hLAlQ==", + "node_modules/@csstools/postcss-content-alt-text": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@csstools/postcss-content-alt-text/-/postcss-content-alt-text-2.0.8.tgz", + "integrity": "sha512-9SfEW9QCxEpTlNMnpSqFaHyzsiRpZ5J5+KqCu1u5/eEJAWsMhzT40qf0FIbeeglEvrGRMdDzAxMIz3wqoGSb+Q==", "dev": true, "funding": [ { @@ -418,10 +519,9 @@ ], "license": "MIT-0", "dependencies": { - "@csstools/css-color-parser": "^3.0.10", "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4", - "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -431,10 +531,10 @@ "postcss": "^8.4" } }, - "node_modules/@csstools/postcss-content-alt-text": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@csstools/postcss-content-alt-text/-/postcss-content-alt-text-2.0.6.tgz", - "integrity": "sha512-eRjLbOjblXq+byyaedQRSrAejKGNAFued+LcbzT+LCL78fabxHkxYjBbxkroONxHHYu2qxhFK2dBStTLPG3jpQ==", + "node_modules/@csstools/postcss-contrast-color-function": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@csstools/postcss-contrast-color-function/-/postcss-contrast-color-function-2.0.12.tgz", + "integrity": "sha512-YbwWckjK3qwKjeYz/CijgcS7WDUCtKTd8ShLztm3/i5dhh4NaqzsbYnhm4bjrpFpnLZ31jVcbK8YL77z3GBPzA==", "dev": true, "funding": [ { @@ -448,9 +548,10 @@ ], "license": "MIT-0", "dependencies": { + "@csstools/css-color-parser": "^3.1.0", "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4", - "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -516,9 +617,9 @@ } }, "node_modules/@csstools/postcss-gamut-mapping": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@csstools/postcss-gamut-mapping/-/postcss-gamut-mapping-2.0.10.tgz", - "integrity": "sha512-QDGqhJlvFnDlaPAfCYPsnwVA6ze+8hhrwevYWlnUeSjkkZfBpcCO42SaUD8jiLlq7niouyLgvup5lh+f1qessg==", + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@csstools/postcss-gamut-mapping/-/postcss-gamut-mapping-2.0.11.tgz", + "integrity": "sha512-fCpCUgZNE2piVJKC76zFsgVW1apF6dpYsqGyH8SIeCcM4pTEsRTWTLCaJIMKFEundsCKwY1rwfhtrio04RJ4Dw==", "dev": true, "funding": [ { @@ -532,7 +633,7 @@ ], "license": "MIT-0", "dependencies": { - "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-color-parser": "^3.1.0", "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4" }, @@ -544,9 +645,9 @@ } }, "node_modules/@csstools/postcss-gradients-interpolation-method": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/@csstools/postcss-gradients-interpolation-method/-/postcss-gradients-interpolation-method-5.0.10.tgz", - "integrity": "sha512-HHPauB2k7Oits02tKFUeVFEU2ox/H3OQVrP3fSOKDxvloOikSal+3dzlyTZmYsb9FlY9p5EUpBtz0//XBmy+aw==", + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/@csstools/postcss-gradients-interpolation-method/-/postcss-gradients-interpolation-method-5.0.12.tgz", + "integrity": "sha512-jugzjwkUY0wtNrZlFeyXzimUL3hN4xMvoPnIXxoZqxDvjZRiSh+itgHcVUWzJ2VwD/VAMEgCLvtaJHX+4Vj3Ow==", "dev": true, "funding": [ { @@ -560,10 +661,10 @@ ], "license": "MIT-0", "dependencies": { - "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-color-parser": "^3.1.0", "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4", - "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -574,9 +675,9 @@ } }, "node_modules/@csstools/postcss-hwb-function": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-4.0.10.tgz", - "integrity": "sha512-nOKKfp14SWcdEQ++S9/4TgRKchooLZL0TUFdun3nI4KPwCjETmhjta1QT4ICQcGVWQTvrsgMM/aLB5We+kMHhQ==", + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-4.0.12.tgz", + "integrity": "sha512-mL/+88Z53KrE4JdePYFJAQWFrcADEqsLprExCM04GDNgHIztwFzj0Mbhd/yxMBngq0NIlz58VVxjt5abNs1VhA==", "dev": true, "funding": [ { @@ -590,10 +691,10 @@ ], "license": "MIT-0", "dependencies": { - "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-color-parser": "^3.1.0", "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4", - "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -604,9 +705,9 @@ } }, "node_modules/@csstools/postcss-ic-unit": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-4.0.2.tgz", - "integrity": "sha512-lrK2jjyZwh7DbxaNnIUjkeDmU8Y6KyzRBk91ZkI5h8nb1ykEfZrtIVArdIjX4DHMIBGpdHrgP0n4qXDr7OHaKA==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-4.0.4.tgz", + "integrity": "sha512-yQ4VmossuOAql65sCPppVO1yfb7hDscf4GseF0VCA/DTDaBc0Wtf8MTqVPfjGYlT5+2buokG0Gp7y0atYZpwjg==", "dev": true, "funding": [ { @@ -620,7 +721,7 @@ ], "license": "MIT-0", "dependencies": { - "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", "@csstools/utilities": "^2.0.0", "postcss-value-parser": "^4.2.0" }, @@ -681,47 +782,10 @@ "postcss": "^8.4" } }, - "node_modules/@csstools/postcss-is-pseudo-class/node_modules/@csstools/selector-specificity": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", - "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT-0", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "postcss-selector-parser": "^7.0.0" - } - }, - "node_modules/@csstools/postcss-is-pseudo-class/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@csstools/postcss-light-dark-function": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/@csstools/postcss-light-dark-function/-/postcss-light-dark-function-2.0.9.tgz", - "integrity": "sha512-1tCZH5bla0EAkFAI2r0H33CDnIBeLUaJh1p+hvvsylJ4svsv2wOmJjJn+OXwUZLXef37GYbRIVKX+X+g6m+3CQ==", + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@csstools/postcss-light-dark-function/-/postcss-light-dark-function-2.0.11.tgz", + "integrity": "sha512-fNJcKXJdPM3Lyrbmgw2OBbaioU7yuKZtiXClf4sGdQttitijYlZMD5K7HrC/eF83VRWRrYq6OZ0Lx92leV2LFA==", "dev": true, "funding": [ { @@ -737,7 +801,7 @@ "dependencies": { "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4", - "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -980,9 +1044,9 @@ } }, "node_modules/@csstools/postcss-oklab-function": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-4.0.10.tgz", - "integrity": "sha512-ZzZUTDd0fgNdhv8UUjGCtObPD8LYxMH+MJsW9xlZaWTV8Ppr4PtxlHYNMmF4vVWGl0T6f8tyWAKjoI6vePSgAg==", + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-4.0.12.tgz", + "integrity": "sha512-HhlSmnE1NKBhXsTnNGjxvhryKtO7tJd1w42DKOGFD6jSHtYOrsJTQDKPMwvOfrzUAk8t7GcpIfRyM7ssqHpFjg==", "dev": true, "funding": [ { @@ -996,10 +1060,10 @@ ], "license": "MIT-0", "dependencies": { - "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-color-parser": "^3.1.0", "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4", - "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -1009,10 +1073,33 @@ "postcss": "^8.4" } }, + "node_modules/@csstools/postcss-position-area-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-position-area-property/-/postcss-position-area-property-1.0.0.tgz", + "integrity": "sha512-fUP6KR8qV2NuUZV3Cw8itx0Ep90aRjAZxAEzC3vrl6yjFv+pFsQbR18UuQctEKmA72K9O27CoYiKEgXxkqjg8Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, "node_modules/@csstools/postcss-progressive-custom-properties": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-4.1.0.tgz", - "integrity": "sha512-YrkI9dx8U4R8Sz2EJaoeD9fI7s7kmeEBfmO+UURNeL6lQI7VxF6sBE+rSqdCBn4onwqmxFdBU3lTwyYb/lCmxA==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-4.2.1.tgz", + "integrity": "sha512-uPiiXf7IEKtUQXsxu6uWtOlRMXd2QWWy5fhxHDnPdXKCQckPP3E34ZgDoZ62r2iT+UOgWsSbM4NvHE5m3mAEdw==", "dev": true, "funding": [ { @@ -1064,9 +1151,9 @@ } }, "node_modules/@csstools/postcss-relative-color-syntax": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@csstools/postcss-relative-color-syntax/-/postcss-relative-color-syntax-3.0.10.tgz", - "integrity": "sha512-8+0kQbQGg9yYG8hv0dtEpOMLwB9M+P7PhacgIzVzJpixxV4Eq9AUQtQw8adMmAJU1RBBmIlpmtmm3XTRd/T00g==", + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/@csstools/postcss-relative-color-syntax/-/postcss-relative-color-syntax-3.0.12.tgz", + "integrity": "sha512-0RLIeONxu/mtxRtf3o41Lq2ghLimw0w9ByLWnnEVuy89exmEEq8bynveBxNW3nyHqLAFEeNtVEmC1QK9MZ8Huw==", "dev": true, "funding": [ { @@ -1080,10 +1167,10 @@ ], "license": "MIT-0", "dependencies": { - "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-color-parser": "^3.1.0", "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4", - "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -1119,20 +1206,6 @@ "postcss": "^8.4" } }, - "node_modules/@csstools/postcss-scope-pseudo-class/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@csstools/postcss-sign-functions": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/@csstools/postcss-sign-functions/-/postcss-sign-functions-1.1.4.tgz", @@ -1189,10 +1262,37 @@ "postcss": "^8.4" } }, + "node_modules/@csstools/postcss-system-ui-font-family": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-system-ui-font-family/-/postcss-system-ui-font-family-1.0.0.tgz", + "integrity": "sha512-s3xdBvfWYfoPSBsikDXbuorcMG1nN1M6GdU0qBsGfcmNR0A/qhloQZpTxjA3Xsyrk1VJvwb2pOfiOT3at/DuIQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, "node_modules/@csstools/postcss-text-decoration-shorthand": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-4.0.2.tgz", - "integrity": "sha512-8XvCRrFNseBSAGxeaVTaNijAu+FzUvjwFXtcrynmazGb/9WUdsPCpBX+mHEHShVRq47Gy4peYAoxYs8ltUnmzA==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-4.0.3.tgz", + "integrity": "sha512-KSkGgZfx0kQjRIYnpsD7X2Om9BUXX/Kii77VBifQW9Ih929hK0KNjVngHDH0bFB9GmfWcR9vJYJJRvw/NQjkrA==", "dev": true, "funding": [ { @@ -1206,7 +1306,7 @@ ], "license": "MIT-0", "dependencies": { - "@csstools/color-helpers": "^5.0.2", + "@csstools/color-helpers": "^5.1.0", "postcss-value-parser": "^4.2.0" }, "engines": { @@ -1267,6 +1367,52 @@ "postcss": "^8.4" } }, + "node_modules/@csstools/selector-resolve-nested": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-resolve-nested/-/selector-resolve-nested-3.1.0.tgz", + "integrity": "sha512-mf1LEW0tJLKfWyvn5KdDrhpxHyuxpbNwTIwOYLIvsTffeyOf85j5oIzfG0yosxDgx/sswlqBnESYUcQH0vgZ0g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.0.0" + } + }, + "node_modules/@csstools/selector-specificity": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", + "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.0.0" + } + }, "node_modules/@csstools/utilities": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@csstools/utilities/-/utilities-2.0.0.tgz", @@ -1291,9 +1437,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", "cpu": [ "ppc64" ], @@ -1304,13 +1450,13 @@ "aix" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", "cpu": [ "arm" ], @@ -1321,13 +1467,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", "cpu": [ "arm64" ], @@ -1338,13 +1484,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", "cpu": [ "x64" ], @@ -1355,13 +1501,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", "cpu": [ "arm64" ], @@ -1372,13 +1518,13 @@ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", "cpu": [ "x64" ], @@ -1389,13 +1535,13 @@ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", "cpu": [ "arm64" ], @@ -1406,13 +1552,13 @@ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", "cpu": [ "x64" ], @@ -1423,13 +1569,13 @@ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", "cpu": [ "arm" ], @@ -1440,13 +1586,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", "cpu": [ "arm64" ], @@ -1457,13 +1603,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", "cpu": [ "ia32" ], @@ -1474,13 +1620,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", "cpu": [ "loong64" ], @@ -1491,13 +1637,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", "cpu": [ "mips64el" ], @@ -1508,13 +1654,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", "cpu": [ "ppc64" ], @@ -1525,13 +1671,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", "cpu": [ "riscv64" ], @@ -1542,13 +1688,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", "cpu": [ "s390x" ], @@ -1559,30 +1705,81 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", "cpu": [ - "x64" + "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "linux" + "openbsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", "cpu": [ "x64" ], @@ -1590,33 +1787,33 @@ "license": "MIT", "optional": true, "os": [ - "netbsd" + "openbsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", "cpu": [ - "x64" + "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "openbsd" + "openharmony" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", "cpu": [ "x64" ], @@ -1627,13 +1824,13 @@ "sunos" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", "cpu": [ "arm64" ], @@ -1644,13 +1841,13 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", "cpu": [ "ia32" ], @@ -1661,13 +1858,13 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", "cpu": [ "x64" ], @@ -1678,13 +1875,13 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "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": { @@ -1714,9 +1911,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true, "license": "MIT", "engines": { @@ -1724,13 +1921,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" }, @@ -1739,19 +1936,22 @@ } }, "node_modules/@eslint/config-helpers": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", - "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", + "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.2", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", - "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", + "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": { @@ -1762,9 +1962,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", - "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", + "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1774,7 +1974,7 @@ "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", + "js-yaml": "^4.1.1", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" }, @@ -1786,9 +1986,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.33.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.33.0.tgz", - "integrity": "sha512-5K1/mKhWaMfreBGJTwval43JJmkip0RmM+3+IuqupeSKNC/Th2Kc7ucaq5ovTSra/OOKB9c58CGSz3QMVbWt0A==", + "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": { @@ -1799,9 +1999,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": { @@ -1809,13 +2009,13 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", - "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", + "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.2", + "@eslint/core": "^0.17.0", "levn": "^0.4.1" }, "engines": { @@ -1823,54 +2023,54 @@ } }, "node_modules/@fortawesome/fontawesome-common-types": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-7.0.0.tgz", - "integrity": "sha512-PGMrIYXLGA5K8RWy8zwBkd4vFi4z7ubxtet6Yn13Plf6krRTwPbdlCwlcfmoX0R7B4Z643QvrtHmdQ5fNtfFCg==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-7.1.0.tgz", + "integrity": "sha512-l/BQM7fYntsCI//du+6sEnHOP6a74UixFyOYUyz2DLMXKx+6DEhfR3F2NYGE45XH1JJuIamacb4IZs9S0ZOWLA==", "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/@fortawesome/fontawesome-svg-core": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-7.0.0.tgz", - "integrity": "sha512-obBEF+zd98r/KtKVW6A+8UGWeaOoyMpl6Q9P3FzHsOnsg742aXsl8v+H/zp09qSSu/a/Hxe9LNKzbBaQq1CEbA==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-7.1.0.tgz", + "integrity": "sha512-fNxRUk1KhjSbnbuBxlWSnBLKLBNun52ZBTcs22H/xEEzM6Ap81ZFTQ4bZBxVQGQgVY0xugKGoRcCbaKjLQ3XZA==", "license": "MIT", "dependencies": { - "@fortawesome/fontawesome-common-types": "7.0.0" + "@fortawesome/fontawesome-common-types": "7.1.0" }, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/free-regular-svg-icons": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-7.0.0.tgz", - "integrity": "sha512-qAh0mTaCY22sQzMK2lKBrtn/aR4keUu5XmtdYR7d702laMe0h+Ab4Kj2pExR9HZkKhjKoq8pbwt8Td+mjW/ipQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-7.1.0.tgz", + "integrity": "sha512-0e2fdEyB4AR+e6kU4yxwA/MonnYcw/CsMEP9lH82ORFi9svA6/RhDyhxIv5mlJaldmaHLLYVTb+3iEr+PDSZuQ==", "license": "(CC-BY-4.0 AND MIT)", "dependencies": { - "@fortawesome/fontawesome-common-types": "7.0.0" + "@fortawesome/fontawesome-common-types": "7.1.0" }, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/free-solid-svg-icons": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-7.0.0.tgz", - "integrity": "sha512-njSLAllkOddYDCXgTFboXn54Oe5FcvpkWq+FoetOHR64PbN0608kM02Lze0xtISGpXgP+i26VyXRQA0Irh3Obw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-7.1.0.tgz", + "integrity": "sha512-Udu3K7SzAo9N013qt7qmm22/wo2hADdheXtBfxFTecp+ogsc0caQNRKEb7pkvvagUGOpG9wJC1ViH6WXs8oXIA==", "license": "(CC-BY-4.0 AND MIT)", "dependencies": { - "@fortawesome/fontawesome-common-types": "7.0.0" + "@fortawesome/fontawesome-common-types": "7.1.0" }, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/vue-fontawesome": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@fortawesome/vue-fontawesome/-/vue-fontawesome-3.1.1.tgz", - "integrity": "sha512-U5azn4mcUVpjHe4JO0Wbe7Ih8e3VbN83EH7OTBtA5/QGw9qcPGffqcmwsLyZYgEkpVkYbq/6dX1Iyl5KUGMp6Q==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@fortawesome/vue-fontawesome/-/vue-fontawesome-3.1.2.tgz", + "integrity": "sha512-mhYnBIuuW8OIMHf31kOjaBmyE7BMrwBorhrOHVud6vTTu+7IPQNWB+DWaHoE75v10dRF5s/dFtcrgE7vKSEWwQ==", "license": "MIT", "peerDependencies": { "@fortawesome/fontawesome-svg-core": "~1 || ~6 || ~7", @@ -1888,33 +2088,19 @@ } }, "node_modules/@humanfs/node": { - "version": "0.16.6", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", - "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", "dev": true, "license": "Apache-2.0", "dependencies": { "@humanfs/core": "^0.19.1", - "@humanwhocodes/retry": "^0.3.0" + "@humanwhocodes/retry": "^0.4.0" }, "engines": { "node": ">=18.18.0" } }, - "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", - "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -2016,9 +2202,9 @@ "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.30", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz", - "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==", + "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": { @@ -2384,9 +2570,9 @@ } }, "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-beta.29", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.29.tgz", - "integrity": "sha512-NIJgOsMjbxAXvoGq/X0gD7VPMQ8j9g0BiDaNjVNVjvl+iKXxL3Jre0v31RmBYeLEmkbj2s02v8vFTbUXi5XS2Q==", + "version": "1.0.0-beta.50", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.50.tgz", + "integrity": "sha512-5e76wQiQVeL1ICOZVUg4LSOVYg9jyhGCin+icYozhsUzM+fHE7kddi1bdiE0jwVqTfkjba3jUFbEkoC9WkdvyA==", "dev": true, "license": "MIT" }, @@ -2437,9 +2623,9 @@ } }, "node_modules/@rollup/pluginutils": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.2.0.tgz", - "integrity": "sha512-qWJ2ZTbmumwiLFomfzTyt5Kng4hwPi9rwCYN4SHb6eaRU1KNO4ccxINHr/VhH4GgPlt1XfSTLX2LBTme8ne4Zw==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", + "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", "dev": true, "license": "MIT", "dependencies": { @@ -2459,23 +2645,10 @@ } } }, - "node_modules/@rollup/pluginutils/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.46.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.46.3.tgz", - "integrity": "sha512-UmTdvXnLlqQNOCJnyksjPs1G4GqXNGW1LrzCe8+8QoaLhhDeTXYBgJ3k6x61WIhlHX2U+VzEJ55TtIjR/HTySA==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz", + "integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==", "cpu": [ "arm" ], @@ -2487,9 +2660,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.46.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.46.3.tgz", - "integrity": "sha512-8NoxqLpXm7VyeI0ocidh335D6OKT0UJ6fHdnIxf3+6oOerZZc+O7r+UhvROji6OspyPm+rrIdb1gTXtVIqn+Sg==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz", + "integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==", "cpu": [ "arm64" ], @@ -2501,9 +2674,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.46.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.46.3.tgz", - "integrity": "sha512-csnNavqZVs1+7/hUKtgjMECsNG2cdB8F7XBHP6FfQjqhjF8rzMzb3SLyy/1BG7YSfQ+bG75Ph7DyedbUqwq1rA==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz", + "integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==", "cpu": [ "arm64" ], @@ -2515,9 +2688,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.46.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.46.3.tgz", - "integrity": "sha512-r2MXNjbuYabSIX5yQqnT8SGSQ26XQc8fmp6UhlYJd95PZJkQD1u82fWP7HqvGUf33IsOC6qsiV+vcuD4SDP6iw==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz", + "integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==", "cpu": [ "x64" ], @@ -2529,9 +2702,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.46.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.46.3.tgz", - "integrity": "sha512-uluObTmgPJDuJh9xqxyr7MV61Imq+0IvVsAlWyvxAaBSNzCcmZlhfYcRhCdMaCsy46ccZa7vtDDripgs9Jkqsw==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz", + "integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==", "cpu": [ "arm64" ], @@ -2543,9 +2716,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.46.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.46.3.tgz", - "integrity": "sha512-AVJXEq9RVHQnejdbFvh1eWEoobohUYN3nqJIPI4mNTMpsyYN01VvcAClxflyk2HIxvLpRcRggpX1m9hkXkpC/A==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz", + "integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==", "cpu": [ "x64" ], @@ -2557,9 +2730,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.46.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.46.3.tgz", - "integrity": "sha512-byyflM+huiwHlKi7VHLAYTKr67X199+V+mt1iRgJenAI594vcmGGddWlu6eHujmcdl6TqSNnvqaXJqZdnEWRGA==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz", + "integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==", "cpu": [ "arm" ], @@ -2571,9 +2744,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.46.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.46.3.tgz", - "integrity": "sha512-aLm3NMIjr4Y9LklrH5cu7yybBqoVCdr4Nvnm8WB7PKCn34fMCGypVNpGK0JQWdPAzR/FnoEoFtlRqZbBBLhVoQ==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz", + "integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==", "cpu": [ "arm" ], @@ -2585,9 +2758,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.46.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.46.3.tgz", - "integrity": "sha512-VtilE6eznJRDIoFOzaagQodUksTEfLIsvXymS+UdJiSXrPW7Ai+WG4uapAc3F7Hgs791TwdGh4xyOzbuzIZrnw==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz", + "integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==", "cpu": [ "arm64" ], @@ -2599,9 +2772,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.46.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.46.3.tgz", - "integrity": "sha512-dG3JuS6+cRAL0GQ925Vppafi0qwZnkHdPeuZIxIPXqkCLP02l7ka+OCyBoDEv8S+nKHxfjvjW4OZ7hTdHkx8/w==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz", + "integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==", "cpu": [ "arm64" ], @@ -2612,10 +2785,10 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.46.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.46.3.tgz", - "integrity": "sha512-iU8DxnxEKJptf8Vcx4XvAUdpkZfaz0KWfRrnIRrOndL0SvzEte+MTM7nDH4A2Now4FvTZ01yFAgj6TX/mZl8hQ==", + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz", + "integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==", "cpu": [ "loong64" ], @@ -2627,9 +2800,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.46.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.46.3.tgz", - "integrity": "sha512-VrQZp9tkk0yozJoQvQcqlWiqaPnLM6uY1qPYXvukKePb0fqaiQtOdMJSxNFUZFsGw5oA5vvVokjHrx8a9Qsz2A==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz", + "integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==", "cpu": [ "ppc64" ], @@ -2641,9 +2814,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.46.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.46.3.tgz", - "integrity": "sha512-uf2eucWSUb+M7b0poZ/08LsbcRgaDYL8NCGjUeFMwCWFwOuFcZ8D9ayPl25P3pl+D2FH45EbHdfyUesQ2Lt9wA==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz", + "integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==", "cpu": [ "riscv64" ], @@ -2655,9 +2828,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.46.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.46.3.tgz", - "integrity": "sha512-7tnUcDvN8DHm/9ra+/nF7lLzYHDeODKKKrh6JmZejbh1FnCNZS8zMkZY5J4sEipy2OW1d1Ncc4gNHUd0DLqkSg==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz", + "integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==", "cpu": [ "riscv64" ], @@ -2669,9 +2842,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.46.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.46.3.tgz", - "integrity": "sha512-MUpAOallJim8CsJK+4Lc9tQzlfPbHxWDrGXZm2z6biaadNpvh3a5ewcdat478W+tXDoUiHwErX/dOql7ETcLqg==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz", + "integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==", "cpu": [ "s390x" ], @@ -2683,9 +2856,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.46.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.46.3.tgz", - "integrity": "sha512-F42IgZI4JicE2vM2PWCe0N5mR5vR0gIdORPqhGQ32/u1S1v3kLtbZ0C/mi9FFk7C5T0PgdeyWEPajPjaUpyoKg==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz", + "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==", "cpu": [ "x64" ], @@ -2697,9 +2870,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.46.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.46.3.tgz", - "integrity": "sha512-oLc+JrwwvbimJUInzx56Q3ujL3Kkhxehg7O1gWAYzm8hImCd5ld1F2Gry5YDjR21MNb5WCKhC9hXgU7rRlyegQ==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz", + "integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==", "cpu": [ "x64" ], @@ -2710,10 +2883,24 @@ "linux" ] }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz", + "integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.46.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.46.3.tgz", - "integrity": "sha512-lOrQ+BVRstruD1fkWg9yjmumhowR0oLAAzavB7yFSaGltY8klttmZtCLvOXCmGE9mLIn8IBV/IFrQOWz5xbFPg==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz", + "integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==", "cpu": [ "arm64" ], @@ -2725,9 +2912,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.46.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.46.3.tgz", - "integrity": "sha512-vvrVKPRS4GduGR7VMH8EylCBqsDcw6U+/0nPDuIjXQRbHJc6xOBj+frx8ksfZAh6+Fptw5wHrN7etlMmQnPQVg==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz", + "integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==", "cpu": [ "ia32" ], @@ -2738,10 +2925,24 @@ "win32" ] }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz", + "integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.46.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.46.3.tgz", - "integrity": "sha512-fi3cPxCnu3ZeM3EwKZPgXbWoGzm2XHgB/WShKI81uj8wG0+laobmqy5wbgEwzstlbLu4MyO8C19FyhhWseYKNQ==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz", + "integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==", "cpu": [ "x64" ], @@ -2753,20 +2954,28 @@ ] }, "node_modules/@rushstack/eslint-patch": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.12.0.tgz", - "integrity": "sha512-5EwMtOqvJMMa3HbmxLlF74e+3/HhwBTMcvt3nqVJgGCozO6hzIPOBlwm8mGVNR9SN2IJpxSnlxczyDjcn7qIyw==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.15.0.tgz", + "integrity": "sha512-ojSshQPKwVvSMR8yT2L/QtUkV5SXi/IfDiJ4/8d6UbTPjiHVmxZzUAzGD8Tzks1b9+qQkZa0isUOvYObedITaw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", + "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", "dev": true, "license": "MIT" }, "node_modules/@types/chai": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.2.tgz", - "integrity": "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", "dev": true, "license": "MIT", "dependencies": { - "@types/deep-eql": "*" + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" } }, "node_modules/@types/deep-eql": { @@ -2791,18 +3000,18 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "24.3.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.0.tgz", - "integrity": "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow==", + "version": "24.10.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", + "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", "license": "MIT", "dependencies": { - "undici-types": "~7.10.0" + "undici-types": "~7.16.0" } }, "node_modules/@types/readable-stream": { - "version": "4.0.21", - "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.21.tgz", - "integrity": "sha512-19eKVv9tugr03IgfXlA9UVUVRbW6IuqRO5B92Dl4a6pT7K8uaGrNS0GkxiZD0BOk6PLuXl5FhWl//eX/pzYdTQ==", + "version": "4.0.22", + "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.22.tgz", + "integrity": "sha512-/FFhJpfCLAPwAcN3mFycNUa77ddnr8jTgF5VmSNetaemWB2cIlfCA9t0YTM3JAT0wOcv8D4tjPo7pkDhK3EJIg==", "license": "MIT", "dependencies": { "@types/node": "*" @@ -2818,13 +3027,13 @@ } }, "node_modules/@vitejs/plugin-vue": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.1.tgz", - "integrity": "sha512-+MaE752hU0wfPFJEUAIxqw18+20euHHdxVtMvbFcOEpjEyfqXH/5DCoTHiVJ0J29EhTJdoTkjEv5YBKU9dnoTw==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.2.tgz", + "integrity": "sha512-iHmwV3QcVGGvSC1BG5bZ4z6iwa1SOpAPWmnjOErd4Ske+lZua5K9TtAVdx0gMBClJ28DViCbSmZitjWZsWO3LA==", "dev": true, "license": "MIT", "dependencies": { - "@rolldown/pluginutils": "1.0.0-beta.29" + "@rolldown/pluginutils": "1.0.0-beta.50" }, "engines": { "node": "^20.19.0 || >=22.12.0" @@ -2835,39 +3044,40 @@ } }, "node_modules/@vitest/expect": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz", - "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==", + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.15.tgz", + "integrity": "sha512-Gfyva9/GxPAWXIWjyGDli9O+waHDC0Q0jaLdFP1qPAUUfo1FEXPXUfUkp3eZA0sSq340vPycSyOlYUeM15Ft1w==", "dev": true, "license": "MIT", "dependencies": { + "@standard-schema/spec": "^1.0.0", "@types/chai": "^5.2.2", - "@vitest/spy": "3.2.4", - "@vitest/utils": "3.2.4", - "chai": "^5.2.0", - "tinyrainbow": "^2.0.0" + "@vitest/spy": "4.0.15", + "@vitest/utils": "4.0.15", + "chai": "^6.2.1", + "tinyrainbow": "^3.0.3" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/mocker": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.4.tgz", - "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.15.tgz", + "integrity": "sha512-CZ28GLfOEIFkvCFngN8Sfx5h+Se0zN+h4B7yOsPVCcgtiO7t5jt9xQh2E1UkFep+eb9fjyMfuC5gBypwb07fvQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.2.4", + "@vitest/spy": "4.0.15", "estree-walker": "^3.0.3", - "magic-string": "^0.30.17" + "magic-string": "^0.30.21" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { "msw": "^2.4.9", - "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + "vite": "^6.0.0 || ^7.0.0-0" }, "peerDependenciesMeta": { "msw": { @@ -2889,98 +3099,79 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz", - "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.15.tgz", + "integrity": "sha512-SWdqR8vEv83WtZcrfLNqlqeQXlQLh2iilO1Wk1gv4eiHKjEzvgHb2OVc3mIPyhZE6F+CtfYjNlDJwP5MN6Km7A==", "dev": true, "license": "MIT", "dependencies": { - "tinyrainbow": "^2.0.0" + "tinyrainbow": "^3.0.3" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/runner": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.4.tgz", - "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==", + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.15.tgz", + "integrity": "sha512-+A+yMY8dGixUhHmNdPUxOh0la6uVzun86vAbuMT3hIDxMrAOmn5ILBHm8ajrqHE0t8R9T1dGnde1A5DTnmi3qw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.2.4", - "pathe": "^2.0.3", - "strip-literal": "^3.0.0" + "@vitest/utils": "4.0.15", + "pathe": "^2.0.3" }, "funding": { "url": "https://opencollective.com/vitest" } }, - "node_modules/@vitest/runner/node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true, - "license": "MIT" - }, "node_modules/@vitest/snapshot": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.4.tgz", - "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==", + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.15.tgz", + "integrity": "sha512-A7Ob8EdFZJIBjLjeO0DZF4lqR6U7Ydi5/5LIZ0xcI+23lYlsYJAfGn8PrIWTYdZQRNnSRlzhg0zyGu37mVdy5g==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.2.4", - "magic-string": "^0.30.17", + "@vitest/pretty-format": "4.0.15", + "magic-string": "^0.30.21", "pathe": "^2.0.3" }, "funding": { "url": "https://opencollective.com/vitest" } }, - "node_modules/@vitest/snapshot/node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true, - "license": "MIT" - }, "node_modules/@vitest/spy": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz", - "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==", + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.15.tgz", + "integrity": "sha512-+EIjOJmnY6mIfdXtE/bnozKEvTC4Uczg19yeZ2vtCz5Yyb0QQ31QWVQ8hswJ3Ysx/K2EqaNsVanjr//2+P3FHw==", "dev": true, "license": "MIT", - "dependencies": { - "tinyspy": "^4.0.3" - }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/utils": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz", - "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==", + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.15.tgz", + "integrity": "sha512-HXjPW2w5dxhTD0dLwtYHDnelK3j8sR8cWIaLxr22evTyY6q8pRCjZSmhRWVjBaOVXChQd6AwMzi9pucorXCPZA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.2.4", - "loupe": "^3.1.4", - "tinyrainbow": "^2.0.0" + "@vitest/pretty-format": "4.0.15", + "tinyrainbow": "^3.0.3" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vue/compiler-core": { - "version": "3.5.18", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.18.tgz", - "integrity": "sha512-3slwjQrrV1TO8MoXgy3aynDQ7lslj5UqDxuHnrzHtpON5CBinhWjJETciPngpin/T3OuW3tXUf86tEurusnztw==", + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.25.tgz", + "integrity": "sha512-vay5/oQJdsNHmliWoZfHPoVZZRmnSWhug0BYT34njkYTPqClh3DNWLkZNJBVSjsNMrg0CCrBfoKkjZQPM/QVUw==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.0", - "@vue/shared": "3.5.18", + "@babel/parser": "^7.28.5", + "@vue/shared": "3.5.25", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" @@ -2999,58 +3190,58 @@ } }, "node_modules/@vue/compiler-dom": { - "version": "3.5.18", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.18.tgz", - "integrity": "sha512-RMbU6NTU70++B1JyVJbNbeFkK+A+Q7y9XKE2EM4NLGm2WFR8x9MbAtWxPPLdm0wUkuZv9trpwfSlL6tjdIa1+A==", + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.25.tgz", + "integrity": "sha512-4We0OAcMZsKgYoGlMjzYvaoErltdFI2/25wqanuTu+S4gismOTRTBPi4IASOjxWdzIwrYSjnqONfKvuqkXzE2Q==", "license": "MIT", "dependencies": { - "@vue/compiler-core": "3.5.18", - "@vue/shared": "3.5.18" + "@vue/compiler-core": "3.5.25", + "@vue/shared": "3.5.25" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.5.18", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.18.tgz", - "integrity": "sha512-5aBjvGqsWs+MoxswZPoTB9nSDb3dhd1x30xrrltKujlCxo48j8HGDNj3QPhF4VIS0VQDUrA1xUfp2hEa+FNyXA==", + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.25.tgz", + "integrity": "sha512-PUgKp2rn8fFsI++lF2sO7gwO2d9Yj57Utr5yEsDf3GNaQcowCLKL7sf+LvVFvtJDXUp/03+dC6f2+LCv5aK1ag==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.0", - "@vue/compiler-core": "3.5.18", - "@vue/compiler-dom": "3.5.18", - "@vue/compiler-ssr": "3.5.18", - "@vue/shared": "3.5.18", + "@babel/parser": "^7.28.5", + "@vue/compiler-core": "3.5.25", + "@vue/compiler-dom": "3.5.25", + "@vue/compiler-ssr": "3.5.25", + "@vue/shared": "3.5.25", "estree-walker": "^2.0.2", - "magic-string": "^0.30.17", + "magic-string": "^0.30.21", "postcss": "^8.5.6", "source-map-js": "^1.2.1" } }, "node_modules/@vue/compiler-ssr": { - "version": "3.5.18", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.18.tgz", - "integrity": "sha512-xM16Ak7rSWHkM3m22NlmcdIM+K4BMyFARAfV9hYFl+SFuRzrZ3uGMNW05kA5pmeMa0X9X963Kgou7ufdbpOP9g==", + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.25.tgz", + "integrity": "sha512-ritPSKLBcParnsKYi+GNtbdbrIE1mtuFEJ4U1sWeuOMlIziK5GtOL85t5RhsNy4uWIXPgk+OUdpnXiTdzn8o3A==", "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.18", - "@vue/shared": "3.5.18" + "@vue/compiler-dom": "3.5.25", + "@vue/shared": "3.5.25" } }, "node_modules/@vue/devtools-api": { - "version": "7.7.7", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.7.tgz", - "integrity": "sha512-lwOnNBH2e7x1fIIbVT7yF5D+YWhqELm55/4ZKf45R9T8r9dE2AIOy8HKjfqzGsoTHFbWbr337O4E0A0QADnjBg==", + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.9.tgz", + "integrity": "sha512-kIE8wvwlcZ6TJTbNeU2HQNtaxLx3a84aotTITUuL/4bzfPxzajGBOoqjMhwZJ8L9qFYDU/lAYMEEm11dnZOD6g==", "license": "MIT", "dependencies": { - "@vue/devtools-kit": "^7.7.7" + "@vue/devtools-kit": "^7.7.9" } }, "node_modules/@vue/devtools-kit": { - "version": "7.7.7", - "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.7.tgz", - "integrity": "sha512-wgoZtxcTta65cnZ1Q6MbAfePVFxfM+gq0saaeytoph7nEa7yMXoi6sCPy4ufO111B9msnw0VOWjPEFCXuAKRHA==", + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.9.tgz", + "integrity": "sha512-PyQ6odHSgiDVd4hnTP+aDk2X4gl2HmLDfiyEnn3/oV+ckFDuswRs4IbBT7vacMuGdwY/XemxBoh302ctbsptuA==", "license": "MIT", "dependencies": { - "@vue/devtools-shared": "^7.7.7", + "@vue/devtools-shared": "^7.7.9", "birpc": "^2.3.0", "hookable": "^5.5.3", "mitt": "^3.0.1", @@ -3060,9 +3251,9 @@ } }, "node_modules/@vue/devtools-shared": { - "version": "7.7.7", - "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.7.tgz", - "integrity": "sha512-+udSj47aRl5aKb0memBvcUG9koarqnxNM5yjuREvqwK6T3ap4mn3Zqqc17QrBFTqSMjr3HK1cvStEZpMDpfdyw==", + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.9.tgz", + "integrity": "sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA==", "license": "MIT", "dependencies": { "rfdc": "^1.4.1" @@ -3084,53 +3275,53 @@ } }, "node_modules/@vue/reactivity": { - "version": "3.5.18", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.18.tgz", - "integrity": "sha512-x0vPO5Imw+3sChLM5Y+B6G1zPjwdOri9e8V21NnTnlEvkxatHEH5B5KEAJcjuzQ7BsjGrKtfzuQ5eQwXh8HXBg==", + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.25.tgz", + "integrity": "sha512-5xfAypCQepv4Jog1U4zn8cZIcbKKFka3AgWHEFQeK65OW+Ys4XybP6z2kKgws4YB43KGpqp5D/K3go2UPPunLA==", "license": "MIT", "dependencies": { - "@vue/shared": "3.5.18" + "@vue/shared": "3.5.25" } }, "node_modules/@vue/runtime-core": { - "version": "3.5.18", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.18.tgz", - "integrity": "sha512-DUpHa1HpeOQEt6+3nheUfqVXRog2kivkXHUhoqJiKR33SO4x+a5uNOMkV487WPerQkL0vUuRvq/7JhRgLW3S+w==", + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.25.tgz", + "integrity": "sha512-Z751v203YWwYzy460bzsYQISDfPjHTl+6Zzwo/a3CsAf+0ccEjQ8c+0CdX1WsumRTHeywvyUFtW6KvNukT/smA==", "license": "MIT", "dependencies": { - "@vue/reactivity": "3.5.18", - "@vue/shared": "3.5.18" + "@vue/reactivity": "3.5.25", + "@vue/shared": "3.5.25" } }, "node_modules/@vue/runtime-dom": { - "version": "3.5.18", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.18.tgz", - "integrity": "sha512-YwDj71iV05j4RnzZnZtGaXwPoUWeRsqinblgVJwR8XTXYZ9D5PbahHQgsbmzUvCWNF6x7siQ89HgnX5eWkr3mw==", + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.25.tgz", + "integrity": "sha512-a4WrkYFbb19i9pjkz38zJBg8wa/rboNERq3+hRRb0dHiJh13c+6kAbgqCPfMaJ2gg4weWD3APZswASOfmKwamA==", "license": "MIT", "dependencies": { - "@vue/reactivity": "3.5.18", - "@vue/runtime-core": "3.5.18", - "@vue/shared": "3.5.18", + "@vue/reactivity": "3.5.25", + "@vue/runtime-core": "3.5.25", + "@vue/shared": "3.5.25", "csstype": "^3.1.3" } }, "node_modules/@vue/server-renderer": { - "version": "3.5.18", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.18.tgz", - "integrity": "sha512-PvIHLUoWgSbDG7zLHqSqaCoZvHi6NNmfVFOqO+OnwvqMz/tqQr3FuGWS8ufluNddk7ZLBJYMrjcw1c6XzR12mA==", + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.25.tgz", + "integrity": "sha512-UJaXR54vMG61i8XNIzTSf2Q7MOqZHpp8+x3XLGtE3+fL+nQd+k7O5+X3D/uWrnQXOdMw5VPih+Uremcw+u1woQ==", "license": "MIT", "dependencies": { - "@vue/compiler-ssr": "3.5.18", - "@vue/shared": "3.5.18" + "@vue/compiler-ssr": "3.5.25", + "@vue/shared": "3.5.25" }, "peerDependencies": { - "vue": "3.5.18" + "vue": "3.5.25" } }, "node_modules/@vue/shared": { - "version": "3.5.18", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.18.tgz", - "integrity": "sha512-cZy8Dq+uuIXbxCZpuLd2GJdeSO/lIzIspC2WtkqIpje5QyFbvLaI5wZtdUjLHjGZrlVX6GilejatWwVYYRc8tA==", + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.25.tgz", + "integrity": "sha512-AbOPdQQnAnzs58H2FrrDxYj/TJfmeS2jdfEEhgiKINy+bnOANmVizIEgq1r+C5zsbs6l1CCQxtcj71rwNQ4jWg==", "license": "MIT" }, "node_modules/@vue/test-utils": { @@ -3217,9 +3408,9 @@ } }, "node_modules/ansi-regex": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz", - "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true, "license": "MIT", "engines": { @@ -3293,9 +3484,9 @@ } }, "node_modules/autoprefixer": { - "version": "10.4.21", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", - "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", + "version": "10.4.22", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.22.tgz", + "integrity": "sha512-ARe0v/t9gO28Bznv6GgqARmVqcWOV3mfgUPn9becPHMiD3o9BwlRgaeccZnwTpZ7Zwqrm+c1sUSsMxIzQzc8Xg==", "dev": true, "funding": [ { @@ -3313,9 +3504,9 @@ ], "license": "MIT", "dependencies": { - "browserslist": "^4.24.4", - "caniuse-lite": "^1.0.30001702", - "fraction.js": "^4.3.7", + "browserslist": "^4.27.0", + "caniuse-lite": "^1.0.30001754", + "fraction.js": "^5.3.4", "normalize-range": "^0.1.2", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" @@ -3372,19 +3563,39 @@ ], "license": "MIT" }, + "node_modules/baseline-browser-mapping": { + "version": "2.9.4", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.4.tgz", + "integrity": "sha512-ZCQ9GEWl73BVm8bu5Fts8nt7MHdbt5vY9bP6WGnUh+r3l8M7CgfyTlwsgCbMC66BNxPr6Xoce3j66Ms5YUQTNA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/bidi-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", + "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "require-from-string": "^2.0.2" + } + }, "node_modules/birpc": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.5.0.tgz", - "integrity": "sha512-VSWO/W6nNQdyP520F1mhf+Lc2f8pjGQOtoHHm7Ze8Go1kX7akpVIrtTa0fn+HB0QJEDVacl6aO08YE0PgXfdnQ==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.9.0.tgz", + "integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/antfu" } }, "node_modules/bl": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/bl/-/bl-6.1.2.tgz", - "integrity": "sha512-6J3oG82fpJ71WF4l0W6XslkwAPMr+Zcp+AmdxJ0L8LsXNzFeO8GYesV2J9AzGArBjrsb2xR50Ocbn/CL1B44TA==", + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/bl/-/bl-6.1.6.tgz", + "integrity": "sha512-jLsPgN/YSvPUg9UX0Kd73CXpm2Psg9FxMeCSXnk3WBO3CMT10JMwijubhGfHCnFu6TPn1ei3b975dxv7K2pWVg==", "license": "MIT", "dependencies": { "@types/readable-stream": "^4.0.0", @@ -3432,15 +3643,15 @@ } }, "node_modules/broker-factory": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/broker-factory/-/broker-factory-3.1.9.tgz", - "integrity": "sha512-MzvndyD6EcbkBtX4NXm/HfdO1+cOR5ONNdMCXEKfHpxGdMtuDz7+o+nJf7HMtyPH1sUVf/lEIP+DMluC5PgaBQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/broker-factory/-/broker-factory-3.1.10.tgz", + "integrity": "sha512-BzqK5GYFhvVFvO13uzPN0SCiOsOQuhMUbsGvTXDJMA2/N4GvIlFdxEuueE+60Zk841bBU5G3+fl2cqYEo0wgGg==", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.28.3", - "fast-unique-numbers": "^9.0.23", + "@babel/runtime": "^7.28.4", + "fast-unique-numbers": "^9.0.24", "tslib": "^2.8.1", - "worker-factory": "^7.0.45" + "worker-factory": "^7.0.46" } }, "node_modules/brorand": { @@ -3510,24 +3721,23 @@ } }, "node_modules/browserify-sign": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.3.tgz", - "integrity": "sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.5.tgz", + "integrity": "sha512-C2AUdAJg6rlM2W5QMp2Q4KGQMVBwR1lIimTsUnutJ8bMpW5B52pGpR2gEnNBNwijumDo5FojQ0L9JrXA8m4YEw==", "license": "ISC", "dependencies": { - "bn.js": "^5.2.1", - "browserify-rsa": "^4.1.0", + "bn.js": "^5.2.2", + "browserify-rsa": "^4.1.1", "create-hash": "^1.2.0", "create-hmac": "^1.1.7", - "elliptic": "^6.5.5", - "hash-base": "~3.0", + "elliptic": "^6.6.1", "inherits": "^2.0.4", - "parse-asn1": "^5.1.7", + "parse-asn1": "^5.1.9", "readable-stream": "^2.3.8", "safe-buffer": "^5.2.1" }, "engines": { - "node": ">= 0.12" + "node": ">= 0.10" } }, "node_modules/browserify-sign/node_modules/isarray": { @@ -3582,9 +3792,9 @@ } }, "node_modules/browserslist": { - "version": "4.25.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.3.tgz", - "integrity": "sha512-cDGv1kkDI4/0e5yON9yM5G/0A5u8sf5TnmdX5C9qHzI9PPu++sQ9zjm1k9NiOrf3riY4OkK0zSGqfvJyJsgCBQ==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", "dev": true, "funding": [ { @@ -3602,10 +3812,11 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001735", - "electron-to-chromium": "^1.5.204", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.3" + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" @@ -3656,16 +3867,6 @@ "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==", "license": "MIT" }, - "node_modules/cac": { - "version": "6.7.14", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -3724,9 +3925,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001735", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001735.tgz", - "integrity": "sha512-EV/laoX7Wq2J9TQlyIXRxTJqIw4sxfXS4OYgudGxBYRuTv0q7AM6yMEpU/Vo1I94thg9U6EZ2NfZx9GJq83u7w==", + "version": "1.0.30001759", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001759.tgz", + "integrity": "sha512-Pzfx9fOKoKvevQf8oCXoyNRQ5QyxJj+3O0Rqx2V5oxT61KGx8+n6hV/IUyJeifUci2clnmmKVpvtiqRzgiWjSw==", "dev": true, "funding": [ { @@ -3745,18 +3946,11 @@ "license": "CC-BY-4.0" }, "node_modules/chai": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.1.tgz", - "integrity": "sha512-48af6xm9gQK8rhIcOxWwdGzIervm8BVTin+yRp9HEvU20BtVZ2lBywlIJBzwaDtvo0FvjeL7QdCADoUoqIbV3A==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.1.tgz", + "integrity": "sha512-p4Z49OGG5W/WBCPSS/dH3jQ73kD6tiMmUM+bckNK6Jr5JHMG3k9bg/BvKR8lKmtVBKmOiuVaV2ws8s9oSbwysg==", "dev": true, "license": "MIT", - "dependencies": { - "assertion-error": "^2.0.1", - "check-error": "^2.1.1", - "deep-eql": "^5.0.1", - "loupe": "^3.1.0", - "pathval": "^2.0.0" - }, "engines": { "node": ">=18" } @@ -3779,9 +3973,9 @@ } }, "node_modules/chart.js": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.5.0.tgz", - "integrity": "sha512-aYeC/jDgSEx8SHWZvANYMioYMZ2KX02W6f6uVfyteuCGcadDLcYVHdfdygsTQkQ4TKn5lghoojAsPj5pu0SnvQ==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.5.1.tgz", + "integrity": "sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw==", "license": "MIT", "dependencies": { "@kurkle/color": "^0.3.0" @@ -3809,24 +4003,31 @@ "chart.js": ">=4.0.0" } }, - "node_modules/check-error": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", - "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, "engines": { - "node": ">= 16" + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, "node_modules/cipher-base": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.6.tgz", - "integrity": "sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.7.tgz", + "integrity": "sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==", "license": "MIT", "dependencies": { "inherits": "^2.0.4", - "safe-buffer": "^5.2.1" + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.2" }, "engines": { "node": ">= 0.10" @@ -3927,15 +4128,15 @@ "license": "MIT" }, "node_modules/copy-anything": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz", - "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-4.0.5.tgz", + "integrity": "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==", "license": "MIT", "dependencies": { - "is-what": "^4.1.8" + "is-what": "^5.2.0" }, "engines": { - "node": ">=12.13" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/mesqueeb" @@ -4063,24 +4264,10 @@ "postcss": "^8.4" } }, - "node_modules/css-blank-pseudo/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/css-has-pseudo": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-7.0.2.tgz", - "integrity": "sha512-nzol/h+E0bId46Kn2dQH5VElaknX2Sr0hFuB/1EomdC7j+OISt2ZzK7EHX9DZDY53WbIVAR7FYKSO2XnSf07MQ==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-7.0.3.tgz", + "integrity": "sha512-oG+vKuGyqe/xvEMoxAQrhi7uY16deJR3i7wwhBerVrGQKSqUC5GiOVxTpM9F9B9hw0J+eKeOWLH7E9gZ1Dr5rA==", "dev": true, "funding": [ { @@ -4105,10 +4292,10 @@ "postcss": "^8.4" } }, - "node_modules/css-has-pseudo/node_modules/@csstools/selector-specificity": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", - "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", + "node_modules/css-prefers-color-scheme": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-10.0.0.tgz", + "integrity": "sha512-VCtXZAWivRglTZditUfB4StnsWr6YVZ2PRtuxQLKTNRdtAf8tpzaVPE9zXIF3VaSc7O70iK/j1+NXxyQCqdPjQ==", "dev": true, "funding": [ { @@ -4125,50 +4312,27 @@ "node": ">=18" }, "peerDependencies": { - "postcss-selector-parser": "^7.0.0" + "postcss": "^8.4" } }, - "node_modules/css-has-pseudo/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "node_modules/css-tree": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz", + "integrity": "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==", "dev": true, "license": "MIT", "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" + "mdn-data": "2.12.2", + "source-map-js": "^1.0.1" }, "engines": { - "node": ">=4" - } - }, - "node_modules/css-prefers-color-scheme": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-10.0.0.tgz", - "integrity": "sha512-VCtXZAWivRglTZditUfB4StnsWr6YVZ2PRtuxQLKTNRdtAf8tpzaVPE9zXIF3VaSc7O70iK/j1+NXxyQCqdPjQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT-0", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "postcss": "^8.4" + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" } }, "node_modules/cssdb": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-8.3.1.tgz", - "integrity": "sha512-XnDRQMXucLueX92yDe0LPKupXetWoFOgawr4O4X41l5TltgK2NVbJJVDnnOywDYfW1sTJ28AcXGKOqdRKwCcmQ==", + "version": "8.5.2", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-8.5.2.tgz", + "integrity": "sha512-Pmoj9RmD8RIoIzA2EQWO4D4RMeDts0tgAH0VXdlNdxjuBGI3a9wMOIcUwaPNmD4r2qtIa06gqkIf7sECl+cBCg==", "dev": true, "funding": [ { @@ -4196,43 +4360,44 @@ } }, "node_modules/cssstyle": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.6.0.tgz", - "integrity": "sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-5.3.3.tgz", + "integrity": "sha512-OytmFH+13/QXONJcC75QNdMtKpceNk3u8ThBjyyYjkEcy/ekBwR1mMAuNvi3gdBPW3N5TlCzQ0WZw8H0lN/bDw==", "dev": true, "license": "MIT", "dependencies": { - "@asamuzakjp/css-color": "^3.2.0", - "rrweb-cssom": "^0.8.0" + "@asamuzakjp/css-color": "^4.0.3", + "@csstools/css-syntax-patches-for-csstree": "^1.0.14", + "css-tree": "^3.1.0" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", "license": "MIT" }, "node_modules/data-urls": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", - "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-6.0.0.tgz", + "integrity": "sha512-BnBS08aLUM+DKamupXs3w2tJJoqU+AkaE/+6vQxi/G/DPmIZFJJp9Dkb1kM03AZx8ADehDUZgsNxju3mPXZYIA==", "dev": true, "license": "MIT", "dependencies": { "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.0.0" + "whatwg-url": "^15.0.0" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -4253,16 +4418,6 @@ "dev": true, "license": "MIT" }, - "node_modules/deep-eql": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", - "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -4424,9 +4579,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.206", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.206.tgz", - "integrity": "sha512-/eucXSTaI8L78l42xPurxdBzPTjAkMVCQO7unZCWk9LnZiwKcSvQUhF4c99NWQLwMQXxjlfoQy0+8m9U2yEDQQ==", + "version": "1.5.266", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.266.tgz", + "integrity": "sha512-kgWEglXvkEfMH7rxP5OSZZwnaDWT7J9EoZCujhnpLbfi0bbNtRkgdX2E3gt0Uer11c61qCYktB3hwkAS325sJg==", "dev": true, "license": "ISC" }, @@ -4509,9 +4664,9 @@ } }, "node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -4519,32 +4674,35 @@ "esbuild": "bin/esbuild" }, "engines": { - "node": ">=12" + "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" } }, "node_modules/escalade": { @@ -4571,25 +4729,24 @@ } }, "node_modules/eslint": { - "version": "9.33.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.33.0.tgz", - "integrity": "sha512-TS9bTNIryDzStCpJN93aC5VRSW3uTx9sClUn4B87pwiCaJh220otoI0X8mJKr+VcPtniMdN8GKjlwgWGUv5ZKA==", + "version": "9.39.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz", + "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", "dev": true, "license": "MIT", "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.1", - "@eslint/core": "^0.15.2", + "@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.33.0", - "@eslint/plugin-kit": "^0.3.5", + "@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", @@ -4679,16 +4836,16 @@ } }, "node_modules/eslint-plugin-vue": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-10.4.0.tgz", - "integrity": "sha512-K6tP0dW8FJVZLQxa2S7LcE1lLw3X8VvB3t887Q6CLrFVxHYBXGANbXvwNzYIu6Ughx1bSJ5BDT0YB3ybPT39lw==", + "version": "10.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-10.6.2.tgz", + "integrity": "sha512-nA5yUs/B1KmKzvC42fyD0+l9Yd+LtEpVhWRbXuDj0e+ZURcTtyRbMDWUeJmTAh2wC6jC83raS63anNM2YT3NPw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "natural-compare": "^1.4.0", "nth-check": "^2.1.1", - "postcss-selector-parser": "^6.0.15", + "postcss-selector-parser": "^7.1.0", "semver": "^7.6.3", "xml-name-validator": "^4.0.0" }, @@ -4696,11 +4853,15 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "peerDependencies": { + "@stylistic/eslint-plugin": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0", "@typescript-eslint/parser": "^7.0.0 || ^8.0.0", "eslint": "^8.57.0 || ^9.0.0", "vue-eslint-parser": "^10.0.0" }, "peerDependenciesMeta": { + "@stylistic/eslint-plugin": { + "optional": true + }, "@typescript-eslint/parser": { "optional": true } @@ -4736,19 +4897,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/espree": { "version": "10.4.0", "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", @@ -4886,18 +5034,36 @@ "license": "MIT" }, "node_modules/fast-unique-numbers": { - "version": "9.0.23", - "resolved": "https://registry.npmjs.org/fast-unique-numbers/-/fast-unique-numbers-9.0.23.tgz", - "integrity": "sha512-jcRIaHo46nfvyvKRMaFSKXmez4jALQ3Qw49gxM5F4siz8HqkyKPPEexpCOYwBSJI1HovrDr4fEedM8QAJ7oX3w==", + "version": "9.0.24", + "resolved": "https://registry.npmjs.org/fast-unique-numbers/-/fast-unique-numbers-9.0.24.tgz", + "integrity": "sha512-Dv0BYn4waOWse94j16rsZ5w/0zoaCa74O3q6IZjMqaXbtT92Q+Sb6pPk+phGzD8Xh+nueQmSRI3tSCaHKidzKw==", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.28.3", + "@babel/runtime": "^7.28.4", "tslib": "^2.8.1" }, "engines": { "node": ">=18.2.0" } }, + "node_modules/fdir": { + "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" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", @@ -4995,16 +5161,16 @@ } }, "node_modules/fraction.js": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", - "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", "dev": true, "license": "MIT", "engines": { "node": "*" }, "funding": { - "type": "patreon", + "type": "github", "url": "https://github.com/sponsors/rawify" } }, @@ -5032,6 +5198,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", @@ -5070,9 +5245,9 @@ } }, "node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "dev": true, "license": "ISC", "dependencies": { @@ -5090,6 +5265,19 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/glob/node_modules/brace-expansion": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", @@ -5339,9 +5527,9 @@ } }, "node_modules/immutable": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.3.tgz", - "integrity": "sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg==", + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.4.tgz", + "integrity": "sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA==", "dev": true, "license": "MIT" }, @@ -5386,9 +5574,9 @@ "license": "ISC" }, "node_modules/ip-address": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz", - "integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", + "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", "license": "MIT", "engines": { "node": ">= 12" @@ -5458,13 +5646,14 @@ } }, "node_modules/is-generator-function": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", - "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "get-proto": "^1.0.0", + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" }, @@ -5556,12 +5745,12 @@ } }, "node_modules/is-what": { - "version": "4.1.16", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz", - "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-5.5.0.tgz", + "integrity": "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==", "license": "MIT", "engines": { - "node": ">=12.13" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/mesqueeb" @@ -5605,18 +5794,6 @@ "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/jiti": { - "version": "1.21.7", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", - "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "bin": { - "jiti": "bin/jiti.js" - } - }, "node_modules/js-beautify": { "version": "1.15.4", "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.4.tgz", @@ -5659,17 +5836,10 @@ "url": "https://opencollective.com/js-sdsl" } }, - "node_modules/js-tokens": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", - "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", - "dev": true, - "license": "MIT" - }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "license": "MIT", "dependencies": { @@ -5680,35 +5850,35 @@ } }, "node_modules/jsdom": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz", - "integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==", + "version": "27.2.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-27.2.0.tgz", + "integrity": "sha512-454TI39PeRDW1LgpyLPyURtB4Zx1tklSr6+OFOipsxGUH1WMTvk6C65JQdrj455+DP2uJ1+veBEHTGFKWVLFoA==", "dev": true, "license": "MIT", "dependencies": { - "cssstyle": "^4.2.1", - "data-urls": "^5.0.0", - "decimal.js": "^10.5.0", + "@acemir/cssom": "^0.9.23", + "@asamuzakjp/dom-selector": "^6.7.4", + "cssstyle": "^5.3.3", + "data-urls": "^6.0.0", + "decimal.js": "^10.6.0", "html-encoding-sniffer": "^4.0.0", "http-proxy-agent": "^7.0.2", "https-proxy-agent": "^7.0.6", "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.16", - "parse5": "^7.2.1", - "rrweb-cssom": "^0.8.0", + "parse5": "^8.0.0", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", - "tough-cookie": "^5.1.1", + "tough-cookie": "^6.0.0", "w3c-xmlserializer": "^5.0.0", - "webidl-conversions": "^7.0.0", + "webidl-conversions": "^8.0.0", "whatwg-encoding": "^3.1.1", "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.1.1", - "ws": "^8.18.0", + "whatwg-url": "^15.1.0", + "ws": "^8.18.3", "xml-name-validator": "^5.0.0" }, "engines": { - "node": ">=18" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { "canvas": "^3.0.0" @@ -5796,35 +5966,32 @@ "dev": true, "license": "MIT" }, - "node_modules/loupe": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.0.tgz", - "integrity": "sha512-2NCfZcT5VGVNX9mSZIxLRkEAegDGBpuQZBy13desuHeVORmBDyAET4TkJr4SjqQy3A8JDofMN6LpkK8Xcm/dlw==", - "dev": true, - "license": "MIT" - }, "node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "license": "ISC" + "version": "11.2.4", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.4.tgz", + "integrity": "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } }, "node_modules/luxon": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.1.tgz", - "integrity": "sha512-RkRWjA926cTvz5rAb1BqyWkKbbjzCGchDUIKMCUvNi17j6f6j8uHGDV82Aqcqtzd+icoYpELmG3ksgGiFNNcNg==", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.2.tgz", + "integrity": "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==", "license": "MIT", "engines": { "node": ">=12" } }, "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==", "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" + "@jridgewell/sourcemap-codec": "^1.5.5" } }, "node_modules/math-intrinsics": { @@ -5847,6 +6014,13 @@ "safe-buffer": "^5.1.2" } }, + "node_modules/mdn-data": { + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz", + "integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==", + "dev": true, + "license": "CC0-1.0" + }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -5862,6 +6036,20 @@ "node": ">=8.6" } }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/miller-rabin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", @@ -5932,9 +6120,9 @@ "license": "MIT" }, "node_modules/mqtt": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-5.14.0.tgz", - "integrity": "sha512-H7EmeCJhbGblbWjm6APF5sAH3SkdI7lxHw/UkblZp8fjSNl8b2MsLcdAkIaQKxvZYmiORkdAjffvKjqQWPkd6w==", + "version": "5.14.1", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-5.14.1.tgz", + "integrity": "sha512-NxkPxE70Uq3Ph7goefQa7ggSsVzHrayCD0OyxlJgITN/EbzlZN+JEPmaAZdxP1LsIT5FamDyILoQTF72W7Nnbw==", "license": "MIT", "dependencies": { "@types/readable-stream": "^4.0.21", @@ -5974,6 +6162,12 @@ "process-nextick-args": "^2.0.1" } }, + "node_modules/mqtt/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -6014,9 +6208,9 @@ "optional": true }, "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "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" }, @@ -6145,13 +6339,6 @@ "js-sdsl": "4.3.0" } }, - "node_modules/nwsapi": { - "version": "2.2.21", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.21.tgz", - "integrity": "sha512-o6nIY3qwiSXl7/LuOU0Dmuctd34Yay0yeuZRLFmDPrrdHpXKFndPj3hM+YEPVHYC5fx2otBx4Ilc/gyYSAUaIA==", - "dev": true, - "license": "MIT" - }, "node_modules/object-inspect": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", @@ -6209,6 +6396,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/obug": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT" + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -6290,16 +6488,15 @@ } }, "node_modules/parse-asn1": { - "version": "5.1.7", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.7.tgz", - "integrity": "sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg==", + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.9.tgz", + "integrity": "sha512-fIYNuZ/HastSb80baGOuPRo1O9cf4baWw5WsAp7dBuUzeTD/BoaG8sVTdlPFksBE2lF21dN+A1AnrpIjSWqHHg==", "license": "ISC", "dependencies": { "asn1.js": "^4.10.1", "browserify-aes": "^1.2.0", "evp_bytestokey": "^1.0.3", - "hash-base": "~3.0", - "pbkdf2": "^3.1.2", + "pbkdf2": "^3.1.5", "safe-buffer": "^5.2.1" }, "engines": { @@ -6307,9 +6504,9 @@ } }, "node_modules/parse5": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", - "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz", + "integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==", "dev": true, "license": "MIT", "dependencies": { @@ -6367,62 +6564,35 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/pathval": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", - "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.16" - } + "license": "ISC" + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" }, "node_modules/pbkdf2": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.3.tgz", - "integrity": "sha512-wfRLBZ0feWRhCIkoMB6ete7czJcnNnqRpcoWQBLqatqXXmelSRqfdDK4F3u9T2s2cXas/hQJcryI/4lAL+XTlA==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.5.tgz", + "integrity": "sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ==", "license": "MIT", "dependencies": { - "create-hash": "~1.1.3", + "create-hash": "^1.2.0", "create-hmac": "^1.1.7", - "ripemd160": "=2.0.1", + "ripemd160": "^2.0.3", "safe-buffer": "^5.2.1", - "sha.js": "^2.4.11", - "to-buffer": "^1.2.0" + "sha.js": "^2.4.12", + "to-buffer": "^1.2.1" }, "engines": { - "node": ">=0.12" - } - }, - "node_modules/pbkdf2/node_modules/create-hash": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", - "integrity": "sha512-snRpch/kwQhcdlnZKYanNF1m0RDlrCdSKQaH87w1FCFPVPNCQ/Il9QJKAX2jVBZddRdaHBMC+zXa9Gw9tmkNUA==", - "license": "MIT", - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "sha.js": "^2.4.0" - } - }, - "node_modules/pbkdf2/node_modules/hash-base": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", - "integrity": "sha512-0TROgQ1/SxE6KmxWSvXHvRj90/Xo1JvZShofnYF+f6ZsGtR4eES7WfrQzPalmyagfKZCXpVnitiRebZulWsbiw==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.1" - } - }, - "node_modules/pbkdf2/node_modules/ripemd160": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", - "integrity": "sha512-J7f4wutN8mdbV08MJnXibYpCOPHR+yzy+iQ/AsjMv2j8cLavQ8VGagDFUwwTAdF8FmRKVeNpbTTEwNHCW1g94w==", - "license": "MIT", - "dependencies": { - "hash-base": "^2.0.0", - "inherits": "^2.0.1" + "node": ">= 0.10" } }, "node_modules/perfect-debounce": { @@ -6438,33 +6608,32 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "optional": true, "engines": { - "node": ">=8.6" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/pinia": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.3.tgz", - "integrity": "sha512-ttXO/InUULUXkMHpTdp9Fj4hLpD/2AoJdmAbAeW2yu1iy1k+pkFekQXw5VpC0/5p51IOR/jDaDRfRWRnMMsGOA==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.4.tgz", + "integrity": "sha512-l7pqLUFTI/+ESXn6k3nu30ZIzW5E2WZF/LaHJEpoq6ElcLD+wduZoB2kBN19du6K/4FDpPMazY2wJr+IndBtQw==", "license": "MIT", "dependencies": { - "@vue/devtools-api": "^7.7.2" + "@vue/devtools-api": "^7.7.7" }, "funding": { "url": "https://github.com/sponsors/posva" }, "peerDependencies": { - "typescript": ">=4.4.4", - "vue": "^2.7.0 || ^3.5.11" + "typescript": ">=4.5.0", + "vue": "^3.5.11" }, "peerDependenciesMeta": { "typescript": { @@ -6547,20 +6716,6 @@ "postcss": "^8.4" } }, - "node_modules/postcss-attribute-case-insensitive/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/postcss-clamp": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/postcss-clamp/-/postcss-clamp-4.1.0.tgz", @@ -6578,9 +6733,9 @@ } }, "node_modules/postcss-color-functional-notation": { - "version": "7.0.10", - "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-7.0.10.tgz", - "integrity": "sha512-k9qX+aXHBiLTRrWoCJuUFI6F1iF6QJQUXNVWJVSbqZgj57jDhBlOvD8gNUGl35tgqDivbGLhZeW3Ongz4feuKA==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-7.0.12.tgz", + "integrity": "sha512-TLCW9fN5kvO/u38/uesdpbx3e8AkTYhMvDZYa9JpmImWuTE99bDQ7GU7hdOADIZsiI9/zuxfAJxny/khknp1Zw==", "dev": true, "funding": [ { @@ -6594,10 +6749,10 @@ ], "license": "MIT-0", "dependencies": { - "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-color-parser": "^3.1.0", "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4", - "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -6749,20 +6904,6 @@ "postcss": "^8.4" } }, - "node_modules/postcss-custom-selectors/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/postcss-dir-pseudo-class": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-9.0.1.tgz", @@ -6789,24 +6930,10 @@ "postcss": "^8.4" } }, - "node_modules/postcss-dir-pseudo-class/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/postcss-double-position-gradients": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-6.0.2.tgz", - "integrity": "sha512-7qTqnL7nfLRyJK/AHSVrrXOuvDDzettC+wGoienURV8v2svNbu6zJC52ruZtHaO6mfcagFmuTGFdzRsJKB3k5Q==", + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-6.0.4.tgz", + "integrity": "sha512-m6IKmxo7FxSP5nF2l63QbCC3r+bWpFUWmZXZf096WxG0m7Vl1Q1+ruFOhpdDRmKrRS+S3Jtk+TVk/7z0+BVK6g==", "dev": true, "funding": [ { @@ -6820,7 +6947,7 @@ ], "license": "MIT-0", "dependencies": { - "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", "@csstools/utilities": "^2.0.0", "postcss-value-parser": "^4.2.0" }, @@ -6857,20 +6984,6 @@ "postcss": "^8.4" } }, - "node_modules/postcss-focus-visible/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/postcss-focus-within": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-9.0.1.tgz", @@ -6897,20 +7010,6 @@ "postcss": "^8.4" } }, - "node_modules/postcss-focus-within/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/postcss-font-variant": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", @@ -6972,9 +7071,9 @@ } }, "node_modules/postcss-lab-function": { - "version": "7.0.10", - "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-7.0.10.tgz", - "integrity": "sha512-tqs6TCEv9tC1Riq6fOzHuHcZyhg4k3gIAMB8GGY/zA1ssGdm6puHMVE7t75aOSoFg7UD2wyrFFhbldiCMyyFTQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-7.0.12.tgz", + "integrity": "sha512-tUcyRk1ZTPec3OuKFsqtRzW2Go5lehW29XA21lZ65XmzQkz43VY2tyWEC202F7W3mILOjw0voOiuxRGTsN+J9w==", "dev": true, "funding": [ { @@ -6988,10 +7087,10 @@ ], "license": "MIT-0", "dependencies": { - "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-color-parser": "^3.1.0", "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4", - "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -7055,66 +7154,6 @@ "postcss": "^8.4" } }, - "node_modules/postcss-nesting/node_modules/@csstools/selector-resolve-nested": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@csstools/selector-resolve-nested/-/selector-resolve-nested-3.1.0.tgz", - "integrity": "sha512-mf1LEW0tJLKfWyvn5KdDrhpxHyuxpbNwTIwOYLIvsTffeyOf85j5oIzfG0yosxDgx/sswlqBnESYUcQH0vgZ0g==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT-0", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "postcss-selector-parser": "^7.0.0" - } - }, - "node_modules/postcss-nesting/node_modules/@csstools/selector-specificity": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", - "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT-0", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "postcss-selector-parser": "^7.0.0" - } - }, - "node_modules/postcss-nesting/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/postcss-opacity-percentage": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-3.0.0.tgz", @@ -7201,9 +7240,9 @@ } }, "node_modules/postcss-preset-env": { - "version": "10.2.4", - "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-10.2.4.tgz", - "integrity": "sha512-q+lXgqmTMdB0Ty+EQ31SuodhdfZetUlwCA/F0zRcd/XdxjzI+Rl2JhZNz5US2n/7t9ePsvuhCnEN4Bmu86zXlA==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-10.5.0.tgz", + "integrity": "sha512-xgxFQPAPxeWmsgy8cR7GM1PGAL/smA5E9qU7K//D4vucS01es3M0fDujhDJn3kY8Ip7/vVYcecbe1yY+vBo3qQ==", "dev": true, "funding": [ { @@ -7217,20 +7256,23 @@ ], "license": "MIT-0", "dependencies": { + "@csstools/postcss-alpha-function": "^1.0.1", "@csstools/postcss-cascade-layers": "^5.0.2", - "@csstools/postcss-color-function": "^4.0.10", - "@csstools/postcss-color-mix-function": "^3.0.10", - "@csstools/postcss-color-mix-variadic-function-arguments": "^1.0.0", - "@csstools/postcss-content-alt-text": "^2.0.6", + "@csstools/postcss-color-function": "^4.0.12", + "@csstools/postcss-color-function-display-p3-linear": "^1.0.1", + "@csstools/postcss-color-mix-function": "^3.0.12", + "@csstools/postcss-color-mix-variadic-function-arguments": "^1.0.2", + "@csstools/postcss-content-alt-text": "^2.0.8", + "@csstools/postcss-contrast-color-function": "^2.0.12", "@csstools/postcss-exponential-functions": "^2.0.9", "@csstools/postcss-font-format-keywords": "^4.0.0", - "@csstools/postcss-gamut-mapping": "^2.0.10", - "@csstools/postcss-gradients-interpolation-method": "^5.0.10", - "@csstools/postcss-hwb-function": "^4.0.10", - "@csstools/postcss-ic-unit": "^4.0.2", + "@csstools/postcss-gamut-mapping": "^2.0.11", + "@csstools/postcss-gradients-interpolation-method": "^5.0.12", + "@csstools/postcss-hwb-function": "^4.0.12", + "@csstools/postcss-ic-unit": "^4.0.4", "@csstools/postcss-initial": "^2.0.1", "@csstools/postcss-is-pseudo-class": "^5.0.3", - "@csstools/postcss-light-dark-function": "^2.0.9", + "@csstools/postcss-light-dark-function": "^2.0.11", "@csstools/postcss-logical-float-and-clear": "^3.0.0", "@csstools/postcss-logical-overflow": "^2.0.0", "@csstools/postcss-logical-overscroll-behavior": "^2.0.0", @@ -7240,38 +7282,40 @@ "@csstools/postcss-media-queries-aspect-ratio-number-values": "^3.0.5", "@csstools/postcss-nested-calc": "^4.0.0", "@csstools/postcss-normalize-display-values": "^4.0.0", - "@csstools/postcss-oklab-function": "^4.0.10", - "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/postcss-oklab-function": "^4.0.12", + "@csstools/postcss-position-area-property": "^1.0.0", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", "@csstools/postcss-random-function": "^2.0.1", - "@csstools/postcss-relative-color-syntax": "^3.0.10", + "@csstools/postcss-relative-color-syntax": "^3.0.12", "@csstools/postcss-scope-pseudo-class": "^4.0.1", "@csstools/postcss-sign-functions": "^1.1.4", "@csstools/postcss-stepped-value-functions": "^4.0.9", - "@csstools/postcss-text-decoration-shorthand": "^4.0.2", + "@csstools/postcss-system-ui-font-family": "^1.0.0", + "@csstools/postcss-text-decoration-shorthand": "^4.0.3", "@csstools/postcss-trigonometric-functions": "^4.0.9", "@csstools/postcss-unset-value": "^4.0.0", - "autoprefixer": "^10.4.21", - "browserslist": "^4.25.0", + "autoprefixer": "^10.4.22", + "browserslist": "^4.28.0", "css-blank-pseudo": "^7.0.1", - "css-has-pseudo": "^7.0.2", + "css-has-pseudo": "^7.0.3", "css-prefers-color-scheme": "^10.0.0", - "cssdb": "^8.3.0", + "cssdb": "^8.5.2", "postcss-attribute-case-insensitive": "^7.0.1", "postcss-clamp": "^4.1.0", - "postcss-color-functional-notation": "^7.0.10", + "postcss-color-functional-notation": "^7.0.12", "postcss-color-hex-alpha": "^10.0.0", "postcss-color-rebeccapurple": "^10.0.0", "postcss-custom-media": "^11.0.6", "postcss-custom-properties": "^14.0.6", "postcss-custom-selectors": "^8.0.5", "postcss-dir-pseudo-class": "^9.0.1", - "postcss-double-position-gradients": "^6.0.2", + "postcss-double-position-gradients": "^6.0.4", "postcss-focus-visible": "^10.0.1", "postcss-focus-within": "^9.0.1", "postcss-font-variant": "^5.0.0", "postcss-gap-properties": "^6.0.0", "postcss-image-set-function": "^7.0.0", - "postcss-lab-function": "^7.0.10", + "postcss-lab-function": "^7.0.12", "postcss-logical": "^8.1.0", "postcss-nesting": "^13.0.2", "postcss-opacity-percentage": "^3.0.0", @@ -7306,27 +7350,13 @@ ], "license": "MIT-0", "dependencies": { - "postcss-selector-parser": "^7.0.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/postcss-pseudo-class-any-link/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" + "postcss-selector-parser": "^7.0.0" }, "engines": { - "node": ">=4" + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" } }, "node_modules/postcss-replace-overflow-wrap": { @@ -7365,24 +7395,10 @@ "postcss": "^8.4" } }, - "node_modules/postcss-selector-not/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "dev": true, "license": "MIT", "dependencies": { @@ -7411,9 +7427,9 @@ } }, "node_modules/prettier": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", - "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.4.tgz", + "integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==", "dev": true, "license": "MIT", "bin": { @@ -7545,13 +7561,37 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", "license": "MIT", "dependencies": { - "is-core-module": "^2.16.0", + "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -7582,19 +7622,79 @@ "license": "MIT" }, "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.3.tgz", + "integrity": "sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==", "license": "MIT", "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" + "hash-base": "^3.1.2", + "inherits": "^2.0.4" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ripemd160/node_modules/hash-base": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.2.tgz", + "integrity": "sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ripemd160/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/ripemd160/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/ripemd160/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/ripemd160/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" } }, + "node_modules/ripemd160/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, "node_modules/rollup": { - "version": "4.46.3", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.46.3.tgz", - "integrity": "sha512-RZn2XTjXb8t5g13f5YclGoilU/kwT696DIkY3sywjdZidNSi3+vseaQov7D7BZXVJCPv3pDWUN69C78GGbXsKw==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", + "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", "dev": true, "license": "MIT", "dependencies": { @@ -7608,26 +7708,28 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.46.3", - "@rollup/rollup-android-arm64": "4.46.3", - "@rollup/rollup-darwin-arm64": "4.46.3", - "@rollup/rollup-darwin-x64": "4.46.3", - "@rollup/rollup-freebsd-arm64": "4.46.3", - "@rollup/rollup-freebsd-x64": "4.46.3", - "@rollup/rollup-linux-arm-gnueabihf": "4.46.3", - "@rollup/rollup-linux-arm-musleabihf": "4.46.3", - "@rollup/rollup-linux-arm64-gnu": "4.46.3", - "@rollup/rollup-linux-arm64-musl": "4.46.3", - "@rollup/rollup-linux-loongarch64-gnu": "4.46.3", - "@rollup/rollup-linux-ppc64-gnu": "4.46.3", - "@rollup/rollup-linux-riscv64-gnu": "4.46.3", - "@rollup/rollup-linux-riscv64-musl": "4.46.3", - "@rollup/rollup-linux-s390x-gnu": "4.46.3", - "@rollup/rollup-linux-x64-gnu": "4.46.3", - "@rollup/rollup-linux-x64-musl": "4.46.3", - "@rollup/rollup-win32-arm64-msvc": "4.46.3", - "@rollup/rollup-win32-ia32-msvc": "4.46.3", - "@rollup/rollup-win32-x64-msvc": "4.46.3", + "@rollup/rollup-android-arm-eabi": "4.53.3", + "@rollup/rollup-android-arm64": "4.53.3", + "@rollup/rollup-darwin-arm64": "4.53.3", + "@rollup/rollup-darwin-x64": "4.53.3", + "@rollup/rollup-freebsd-arm64": "4.53.3", + "@rollup/rollup-freebsd-x64": "4.53.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", + "@rollup/rollup-linux-arm-musleabihf": "4.53.3", + "@rollup/rollup-linux-arm64-gnu": "4.53.3", + "@rollup/rollup-linux-arm64-musl": "4.53.3", + "@rollup/rollup-linux-loong64-gnu": "4.53.3", + "@rollup/rollup-linux-ppc64-gnu": "4.53.3", + "@rollup/rollup-linux-riscv64-gnu": "4.53.3", + "@rollup/rollup-linux-riscv64-musl": "4.53.3", + "@rollup/rollup-linux-s390x-gnu": "4.53.3", + "@rollup/rollup-linux-x64-gnu": "4.53.3", + "@rollup/rollup-linux-x64-musl": "4.53.3", + "@rollup/rollup-openharmony-arm64": "4.53.3", + "@rollup/rollup-win32-arm64-msvc": "4.53.3", + "@rollup/rollup-win32-ia32-msvc": "4.53.3", + "@rollup/rollup-win32-x64-gnu": "4.53.3", + "@rollup/rollup-win32-x64-msvc": "4.53.3", "fsevents": "~2.3.2" } }, @@ -7644,13 +7746,6 @@ "rollup": "^1.20.0 || ^2.0.0 || ^3.0.0 || ^4.0.0" } }, - "node_modules/rrweb-cssom": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", - "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", - "dev": true, - "license": "MIT" - }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -7696,9 +7791,9 @@ "license": "MIT" }, "node_modules/sass": { - "version": "1.90.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.90.0.tgz", - "integrity": "sha512-9GUyuksjw70uNpb1MTYWsH9MQHOHY6kwfnkafC24+7aOMZn9+rVMBxRbLvw756mrBFbIsFg6Xw9IkR2Fnn3k+Q==", + "version": "1.94.2", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.94.2.tgz", + "integrity": "sha512-N+7WK20/wOr7CzA2snJcUSSNTCzeCGUTFY3OgeQP3mZ1aj9NMQ0mSTXwlrnd89j33zzQJGqIN52GIOmYrfq46A==", "dev": true, "license": "MIT", "dependencies": { @@ -7716,36 +7811,6 @@ "@parcel/watcher": "^2.4.1" } }, - "node_modules/sass/node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/sass/node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/saxes": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", @@ -7760,9 +7825,9 @@ } }, "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": { @@ -8027,9 +8092,9 @@ "license": "MIT" }, "node_modules/std-env": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz", - "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==", + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", "dev": true, "license": "MIT" }, @@ -8157,9 +8222,9 @@ } }, "node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", "dev": true, "license": "MIT", "dependencies": { @@ -8209,26 +8274,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strip-literal": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.0.0.tgz", - "integrity": "sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==", - "dev": true, - "license": "MIT", - "dependencies": { - "js-tokens": "^9.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, "node_modules/superjson": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.2.tgz", - "integrity": "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==", + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.6.tgz", + "integrity": "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==", "license": "MIT", "dependencies": { - "copy-anything": "^3.0.2" + "copy-anything": "^4" }, "engines": { "node": ">=16" @@ -8283,14 +8335,14 @@ } }, "node_modules/terser": { - "version": "5.43.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.43.1.tgz", - "integrity": "sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==", + "version": "5.44.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.1.tgz", + "integrity": "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.14.0", + "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -8328,21 +8380,24 @@ "license": "MIT" }, "node_modules/tinyexec": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", - "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", + "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=18" + } }, "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" @@ -8351,61 +8406,10 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/tinyglobby/node_modules/fdir": { - "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" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/tinypool": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", - "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.0.0 || >=20.0.0" - } - }, "node_modules/tinyrainbow": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", - "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tinyspy": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.3.tgz", - "integrity": "sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz", + "integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==", "dev": true, "license": "MIT", "engines": { @@ -8413,29 +8417,29 @@ } }, "node_modules/tldts": { - "version": "6.1.86", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", - "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==", + "version": "7.0.19", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.19.tgz", + "integrity": "sha512-8PWx8tvC4jDB39BQw1m4x8y5MH1BcQ5xHeL2n7UVFulMPH/3Q0uiamahFJ3lXA0zO2SUyRXuVVbWSDmstlt9YA==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^6.1.86" + "tldts-core": "^7.0.19" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "6.1.86", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz", - "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", + "version": "7.0.19", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.19.tgz", + "integrity": "sha512-lJX2dEWx0SGH4O6p+7FPwYmJ/bu1JbcGJ8RLaG9b7liIgZ85itUVEPbMtWRVrde/0fnDPEPHW10ZsKW3kVsE9A==", "dev": true, "license": "MIT" }, "node_modules/to-buffer": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.1.tgz", - "integrity": "sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz", + "integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==", "license": "MIT", "dependencies": { "isarray": "^2.0.5", @@ -8461,29 +8465,29 @@ } }, "node_modules/tough-cookie": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", - "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.0.tgz", + "integrity": "sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "tldts": "^6.1.32" + "tldts": "^7.0.5" }, "engines": { "node": ">=16" } }, "node_modules/tr46": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", - "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz", + "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==", "dev": true, "license": "MIT", "dependencies": { "punycode": "^2.3.1" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/tr46/node_modules/punycode": { @@ -8542,15 +8546,15 @@ "license": "MIT" }, "node_modules/undici-types": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", - "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", "license": "MIT" }, "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.2.tgz", + "integrity": "sha512-E85pfNzMQ9jpKkA7+TJAi4TJN+tBCuWh5rUcS/sv6cFi+1q9LYDwDI5dpUL0u/73EElyQ8d3TEaeW4sPedBqYA==", "dev": true, "funding": [ { @@ -8631,21 +8635,24 @@ "license": "MIT" }, "node_modules/vite": { - "version": "5.4.19", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz", - "integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==", + "version": "7.2.7", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.7.tgz", + "integrity": "sha512-ITcnkFeR3+fI8P1wMgItjGrR10170d8auB4EpMLPqmx6uxElH3a/hHGQabSHKdqd4FXWO1nFIp9rRn7JQ34ACQ==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" + "esbuild": "^0.25.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": "^20.19.0 || >=22.12.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" @@ -8654,19 +8661,25 @@ "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" }, "peerDependenciesMeta": { "@types/node": { "optional": true }, + "jiti": { + "optional": true + }, "less": { "optional": true }, @@ -8687,39 +8700,15 @@ }, "terser": { "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true } } }, - "node_modules/vite-node": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz", - "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cac": "^6.7.14", - "debug": "^4.4.1", - "es-module-lexer": "^1.7.0", - "pathe": "^2.0.3", - "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" - }, - "bin": { - "vite-node": "vite-node.mjs" - }, - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/vite-node/node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true, - "license": "MIT" - }, "node_modules/vite-plugin-node-polyfills": { "version": "0.24.0", "resolved": "https://registry.npmjs.org/vite-plugin-node-polyfills/-/vite-plugin-node-polyfills-0.24.0.tgz", @@ -8738,51 +8727,50 @@ } }, "node_modules/vitest": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.4.tgz", - "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.15.tgz", + "integrity": "sha512-n1RxDp8UJm6N0IbJLQo+yzLZ2sQCDyl1o0LeugbPWf8+8Fttp29GghsQBjYJVmWq3gBFfe9Hs1spR44vovn2wA==", "dev": true, "license": "MIT", "dependencies": { - "@types/chai": "^5.2.2", - "@vitest/expect": "3.2.4", - "@vitest/mocker": "3.2.4", - "@vitest/pretty-format": "^3.2.4", - "@vitest/runner": "3.2.4", - "@vitest/snapshot": "3.2.4", - "@vitest/spy": "3.2.4", - "@vitest/utils": "3.2.4", - "chai": "^5.2.0", - "debug": "^4.4.1", - "expect-type": "^1.2.1", - "magic-string": "^0.30.17", + "@vitest/expect": "4.0.15", + "@vitest/mocker": "4.0.15", + "@vitest/pretty-format": "4.0.15", + "@vitest/runner": "4.0.15", + "@vitest/snapshot": "4.0.15", + "@vitest/spy": "4.0.15", + "@vitest/utils": "4.0.15", + "es-module-lexer": "^1.7.0", + "expect-type": "^1.2.2", + "magic-string": "^0.30.21", + "obug": "^2.1.1", "pathe": "^2.0.3", - "picomatch": "^4.0.2", - "std-env": "^3.9.0", + "picomatch": "^4.0.3", + "std-env": "^3.10.0", "tinybench": "^2.9.0", - "tinyexec": "^0.3.2", - "tinyglobby": "^0.2.14", - "tinypool": "^1.1.1", - "tinyrainbow": "^2.0.0", - "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", - "vite-node": "3.2.4", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.0.3", + "vite": "^6.0.0 || ^7.0.0", "why-is-node-running": "^2.3.0" }, "bin": { "vitest": "vitest.mjs" }, "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { "@edge-runtime/vm": "*", - "@types/debug": "^4.1.12", - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.2.4", - "@vitest/ui": "3.2.4", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.0.15", + "@vitest/browser-preview": "4.0.15", + "@vitest/browser-webdriverio": "4.0.15", + "@vitest/ui": "4.0.15", "happy-dom": "*", "jsdom": "*" }, @@ -8790,13 +8778,19 @@ "@edge-runtime/vm": { "optional": true }, - "@types/debug": { + "@opentelemetry/api": { "optional": true }, "@types/node": { "optional": true }, - "@vitest/browser": { + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { "optional": true }, "@vitest/ui": { @@ -8810,26 +8804,6 @@ } } }, - "node_modules/vitest/node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true, - "license": "MIT" - }, - "node_modules/vitest/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/vm-browserify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", @@ -8837,16 +8811,16 @@ "license": "MIT" }, "node_modules/vue": { - "version": "3.5.18", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.18.tgz", - "integrity": "sha512-7W4Y4ZbMiQ3SEo+m9lnoNpV9xG7QVMLa+/0RFwwiAVkeYoyGXqWE85jabU4pllJNUzqfLShJ5YLptewhCWUgNA==", + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.25.tgz", + "integrity": "sha512-YLVdgv2K13WJ6n+kD5owehKtEXwdwXuj2TTyJMsO7pSeKw2bfRNZGjhB7YzrpbMYj5b5QsUebHpOqR3R3ziy/g==", "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.18", - "@vue/compiler-sfc": "3.5.18", - "@vue/runtime-dom": "3.5.18", - "@vue/server-renderer": "3.5.18", - "@vue/shared": "3.5.18" + "@vue/compiler-dom": "3.5.25", + "@vue/compiler-sfc": "3.5.25", + "@vue/runtime-dom": "3.5.25", + "@vue/server-renderer": "3.5.25", + "@vue/shared": "3.5.25" }, "peerDependencies": { "typescript": "*" @@ -8858,9 +8832,9 @@ } }, "node_modules/vue-chartjs": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/vue-chartjs/-/vue-chartjs-5.3.2.tgz", - "integrity": "sha512-NrkbRRoYshbXbWqJkTN6InoDVwVb90C0R7eAVgMWcB9dPikbruaOoTFjFYHE/+tNPdIe6qdLCDjfjPHQ0fw4jw==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/vue-chartjs/-/vue-chartjs-5.3.3.tgz", + "integrity": "sha512-jqxtL8KZ6YJ5NTv6XzrzLS7osyegOi28UGNZW0h9OkDL7Sh1396ht4Dorh04aKrl2LiSalQ84WtqiG0RIJb0tA==", "license": "MIT", "peerDependencies": { "chart.js": "^4.1.1", @@ -8900,9 +8874,9 @@ } }, "node_modules/vue-router": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.5.1.tgz", - "integrity": "sha512-ogAF3P97NPm8fJsE4by9dwSYtDwXIY1nFY9T6DyQnGHd1E2Da94w9JIolpe42LJGIl0DwOHBi8TcRPlPGwbTtw==", + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.6.3.tgz", + "integrity": "sha512-ARBedLm9YlbvQomnmq91Os7ck6efydTSpRP3nuOKCvgJOHNrhRoJDSKtee8kcL1Vf7nz6U+PMBL+hTvR3bTVQg==", "license": "MIT", "dependencies": { "@vue/devtools-api": "^6.6.4" @@ -8911,7 +8885,7 @@ "url": "https://github.com/sponsors/posva" }, "peerDependencies": { - "vue": "^3.2.0" + "vue": "^3.5.0" } }, "node_modules/vue-router/node_modules/@vue/devtools-api": { @@ -8944,13 +8918,13 @@ } }, "node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.0.tgz", + "integrity": "sha512-n4W4YFyz5JzOfQeA8oN7dUYpR+MBP3PIUsn2jLjWXwK5ASUzt0Jc/A5sAUZoCYFJRGF0FBKJ+1JjN43rNdsQzA==", "dev": true, "license": "BSD-2-Clause", "engines": { - "node": ">=12" + "node": ">=20" } }, "node_modules/whatwg-encoding": { @@ -8977,17 +8951,17 @@ } }, "node_modules/whatwg-url": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", - "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-15.1.0.tgz", + "integrity": "sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==", "dev": true, "license": "MIT", "dependencies": { - "tr46": "^5.1.0", - "webidl-conversions": "^7.0.0" + "tr46": "^6.0.0", + "webidl-conversions": "^8.0.0" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/which": { @@ -9055,50 +9029,50 @@ } }, "node_modules/worker-factory": { - "version": "7.0.45", - "resolved": "https://registry.npmjs.org/worker-factory/-/worker-factory-7.0.45.tgz", - "integrity": "sha512-FFPCiSv7MD6ZDEfiik/ErM8IrIAWajaXhezLyCo3v0FjhUWud6GXnG2BiTE91jLywXGAVCT8IF48Hhr+D/omMw==", + "version": "7.0.46", + "resolved": "https://registry.npmjs.org/worker-factory/-/worker-factory-7.0.46.tgz", + "integrity": "sha512-Sr1hq2FMgNa04UVhYQacsw+i58BtMimzDb4+CqYphZ97OfefRpURu0UZ+JxMr/H36VVJBfuVkxTK7MytsanC3w==", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.28.3", - "fast-unique-numbers": "^9.0.23", + "@babel/runtime": "^7.28.4", + "fast-unique-numbers": "^9.0.24", "tslib": "^2.8.1" } }, "node_modules/worker-timers": { - "version": "8.0.24", - "resolved": "https://registry.npmjs.org/worker-timers/-/worker-timers-8.0.24.tgz", - "integrity": "sha512-Ydu/7TRHlxIRjYSGDge1F92L7y9kzInpwR4CkocRVObPE0eRqC6d+0GFh52Hm+m520RHVKiytOERtCUu5sQDVQ==", + "version": "8.0.25", + "resolved": "https://registry.npmjs.org/worker-timers/-/worker-timers-8.0.25.tgz", + "integrity": "sha512-X7Z5dmM6PlrEnaadtFQOyXHGD/IysPA3HZzaC2koqsU1VI+RvyGmjiiLiUBQixK8PH5R7ilkOzZupWskNRaXmA==", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.28.3", + "@babel/runtime": "^7.28.4", "tslib": "^2.8.1", - "worker-timers-broker": "^8.0.10", - "worker-timers-worker": "^9.0.10" + "worker-timers-broker": "^8.0.11", + "worker-timers-worker": "^9.0.11" } }, "node_modules/worker-timers-broker": { - "version": "8.0.10", - "resolved": "https://registry.npmjs.org/worker-timers-broker/-/worker-timers-broker-8.0.10.tgz", - "integrity": "sha512-xvo/9GiuduENbJNdWnvZtkriIkjBKKVbMyw7GXvrBu3n1JHemzZgxqaCcCBNlpfXnRXXF4ekqvXWLh1gb65b8w==", + "version": "8.0.11", + "resolved": "https://registry.npmjs.org/worker-timers-broker/-/worker-timers-broker-8.0.11.tgz", + "integrity": "sha512-uwhxKru8BI9m2tsogxr2fB6POZ8LB2xH+Pu3R0mvQnAZLPgLD6K3IX4LNKPTEgTJ/j5VsuQPB+gLI1NBNKkPlg==", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.28.3", - "broker-factory": "^3.1.9", - "fast-unique-numbers": "^9.0.23", + "@babel/runtime": "^7.28.4", + "broker-factory": "^3.1.10", + "fast-unique-numbers": "^9.0.24", "tslib": "^2.8.1", - "worker-timers-worker": "^9.0.10" + "worker-timers-worker": "^9.0.11" } }, "node_modules/worker-timers-worker": { - "version": "9.0.10", - "resolved": "https://registry.npmjs.org/worker-timers-worker/-/worker-timers-worker-9.0.10.tgz", - "integrity": "sha512-cfCmAkuoN+nGGJShta/g7CQVP3h7rvQA642EQg72fOHCWP5S2P83rLxDiaGv811Hd+19Cgdqt/tpRBIZ5kj/dw==", + "version": "9.0.11", + "resolved": "https://registry.npmjs.org/worker-timers-worker/-/worker-timers-worker-9.0.11.tgz", + "integrity": "sha512-pArb5xtgHWImYpXhjg1OFv7JFG0ubmccb73TFoXHXjG830fFj+16N57q9YeBnZX52dn+itRrMoJZ9HaZBVzDaA==", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.28.3", + "@babel/runtime": "^7.28.4", "tslib": "^2.8.1", - "worker-factory": "^7.0.45" + "worker-factory": "^7.0.46" } }, "node_modules/wrap-ansi": { @@ -9184,9 +9158,9 @@ } }, "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "dev": true, "license": "MIT", "engines": { diff --git a/packages/modules/display_themes/cards/source/package.json b/packages/modules/display_themes/cards/source/package.json index e8145f2fc1..edbc46434e 100644 --- a/packages/modules/display_themes/cards/source/package.json +++ b/packages/modules/display_themes/cards/source/package.json @@ -12,40 +12,40 @@ "build-dev": "vite build --mode=development --out-dir=../web/ --emptyOutDir" }, "dependencies": { - "@fortawesome/fontawesome-svg-core": "^7.0.0", - "@fortawesome/free-regular-svg-icons": "^7.0.0", - "@fortawesome/free-solid-svg-icons": "^7.0.0", - "@fortawesome/vue-fontawesome": "^3.1.1", + "@fortawesome/fontawesome-svg-core": "^7.1.0", + "@fortawesome/free-regular-svg-icons": "^7.1.0", + "@fortawesome/free-solid-svg-icons": "^7.1.0", + "@fortawesome/vue-fontawesome": "^3.1.2", "@inkline/inkline": "^3.2.2", "buffer": "^6.0.3", - "chart.js": "^4.5.0", + "chart.js": "^4.5.1", "chartjs-adapter-luxon": "^1.3.1", "chartjs-plugin-annotation": "^3.1.0", "events": "^3.3.0", - "luxon": "^3.7.1", - "mqtt": "^5.14.0", + "luxon": "^3.7.2", + "mqtt": "^5.14.1", "node-stdlib-browser": "^1.3.1", - "pinia": "^3.0.3", + "pinia": "^3.0.4", "vue": "^3.5.18", - "vue-chartjs": "^5.3.2", - "vue-router": "^4.5.1" + "vue-chartjs": "^5.3.3", + "vue-router": "^4.6.3" }, "devDependencies": { "@rollup/plugin-terser": "^0.4.4", - "@rushstack/eslint-patch": "^1.12.0", - "@vitejs/plugin-vue": "^6.0.1", + "@rushstack/eslint-patch": "^1.15.0", + "@vitejs/plugin-vue": "^6.0.2", "@vue/eslint-config-prettier": "^10.2.0", "@vue/test-utils": "^2.4.6", - "eslint": "^9.33.0", - "eslint-plugin-vue": "^10.4.0", - "jsdom": "^26.1.0", + "eslint": "^9.39.1", + "eslint-plugin-vue": "^10.6.2", + "jsdom": "^27.2.0", "postcss": "^8.5.6", - "postcss-preset-env": "^10.2.4", - "prettier": "^3.6.2", + "postcss-preset-env": "^10.5.0", + "prettier": "^3.7.4", "rollup-plugin-polyfill-node": "^0.13.0", - "sass": "^1.90.0", - "vite": "^5.4.19", + "sass": "^1.94.2", + "vite": "^7.2.7", "vite-plugin-node-polyfills": "^0.24.0", - "vitest": "^3.2.4" + "vitest": "^4.0.15" } } diff --git a/packages/modules/display_themes/cards/source/src/components/DashboardCard.vue b/packages/modules/display_themes/cards/source/src/components/DashboardCard.vue index 8e06af1dbb..09d914b62f 100644 --- a/packages/modules/display_themes/cards/source/src/components/DashboardCard.vue +++ b/packages/modules/display_themes/cards/source/src/components/DashboardCard.vue @@ -29,8 +29,8 @@ export default {