diff --git a/.cursor/commands/oldfkchecks.md b/.cursor/commands/oldfkchecks.md new file mode 100644 index 0000000..e69de29 diff --git a/.gitignore b/.gitignore index 8a8d91a..a4d801f 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ frontend/.env backend/.env backend/images/* +backend/backend-debug.log +backend/*.log \ No newline at end of file diff --git a/PERMISSIONS_GUIDE.md b/PERMISSIONS_GUIDE.md new file mode 100644 index 0000000..e65be02 --- /dev/null +++ b/PERMISSIONS_GUIDE.md @@ -0,0 +1,210 @@ +# Berechtigungssystem - Dokumentation + +## Übersicht + +Das Trainingstagebuch verfügt nun über ein vollständiges rollenbasiertes Berechtigungssystem (RBAC - Role-Based Access Control). Der Club-Ersteller hat automatisch Admin-Rechte und kann anderen Mitgliedern Rollen und spezifische Berechtigungen zuweisen. + +## Rollen + +### 1. Administrator (admin) +- **Vollzugriff** auf alle Funktionen +- Kann Berechtigungen anderer Benutzer verwalten +- Der Club-Ersteller ist automatisch Administrator und kann nicht degradiert werden + +### 2. Trainer (trainer) +- Kann Trainingseinheiten planen und verwalten +- Kann Mitglieder anlegen und bearbeiten +- Kann Spielpläne einsehen und bearbeiten +- Kann Turniere organisieren +- **Kann nicht**: Einstellungen ändern, Berechtigungen verwalten + +### 3. Mannschaftsführer (team_manager) +- Kann Teams und Spielpläne verwalten +- Kann Spieler für Matches einteilen +- Kann Spielergebnisse eintragen +- **Kann nicht**: Trainingseinheiten planen, Mitglieder verwalten + +### 4. Mitglied (member) +- Nur Lesezugriff auf alle Bereiche +- Kann eigene Daten einsehen +- **Kann nicht**: Daten ändern oder löschen + +## Berechtigungsbereiche + +- **diary**: Trainingstagebuch +- **members**: Mitgliederverwaltung +- **teams**: Team-Management +- **schedule**: Spielpläne +- **tournaments**: Turniere +- **statistics**: Statistiken +- **settings**: Einstellungen +- **permissions**: Berechtigungsverwaltung +- **mytischtennis**: MyTischtennis-Integration (für alle zugänglich) + +## Backend-Integration + +### Migration ausführen + +```sql +mysql -u username -p database_name < backend/migrations/add_permissions_to_user_club.sql +``` + +### Authorization Middleware verwenden + +```javascript +import { authorize, requireAdmin, requireOwner } from '../middleware/authorizationMiddleware.js'; + +// Beispiel: Nur Lesezugriff erforderlich +router.get('/diary/:clubId', authenticate, authorize('diary', 'read'), getDiary); + +// Beispiel: Schreibzugriff erforderlich +router.post('/diary/:clubId', authenticate, authorize('diary', 'write'), createDiary); + +// Beispiel: Admin-Rechte erforderlich +router.put('/settings/:clubId', authenticate, requireAdmin(), updateSettings); + +// Beispiel: Nur Owner +router.delete('/club/:clubId', authenticate, requireOwner(), deleteClub); +``` + +### Permission Service verwenden + +```javascript +import permissionService from '../services/permissionService.js'; + +// Berechtigungen prüfen +const hasPermission = await permissionService.hasPermission(userId, clubId, 'diary', 'write'); + +// Rolle setzen +await permissionService.setUserRole(userId, clubId, 'trainer', adminUserId); + +// Custom Permissions setzen +await permissionService.setCustomPermissions( + userId, + clubId, + { diary: { write: false }, members: { write: true } }, + adminUserId +); +``` + +## Frontend-Integration + +### Composable verwenden + +```vue + +``` + +### Direktiven verwenden + +```vue + + + Bearbeiten + + + Löschen + + + Inhalt nur für Berechtigte + + + Admin-Bereich + + + Owner-Bereich + +``` + +### Store verwenden + +```javascript +import { useStore } from 'vuex'; + +const store = useStore(); + +// Berechtigungen abrufen +const permissions = store.getters.currentPermissions; +const hasPermission = store.getters.hasPermission('diary', 'write'); +const isOwner = store.getters.isClubOwner; +const userRole = store.getters.userRole; + +// Berechtigungen laden (wird automatisch beim Club-Wechsel gemacht) +await store.dispatch('loadPermissions', clubId); +``` + +## Admin-UI + +Die Berechtigungsverwaltung ist unter `/permissions` verfügbar und nur für Administratoren sichtbar. + +**Funktionen:** +- Übersicht aller Clubmitglieder mit ihren Rollen +- Rollen zuweisen/ändern +- Custom Permissions für einzelne Benutzer definieren +- Erklärung der verfügbaren Rollen + +## MyTischtennis-Integration + +Die MyTischtennis-Einstellungen und -Funktionen sind für **alle Club-Mitglieder** zugänglich, unabhängig von ihrer Rolle. Dies ermöglicht es jedem, die Anbindung einzurichten und Daten abzurufen. + +## Sicherheitshinweise + +1. **Der Club-Ersteller** (Owner) kann nicht degradiert oder gelöscht werden +2. **Owner-Rechte** können nicht übertragen werden +3. **Backend-Validierung** wird immer durchgeführt, auch wenn das Frontend Elemente ausblendet +4. **Alle API-Routen** sind durch Middleware geschützt +5. **Permissions werden gecacht** im localStorage für bessere Performance + +## Beispiel-Szenarien + +### Szenario 1: Trainer hinzufügen +1. Admin öffnet `/permissions` +2. Wählt Benutzer aus +3. Ändert Rolle zu "Trainer" +4. Benutzer kann jetzt Trainingseinheiten planen + +### Szenario 2: Custom Permissions +1. Admin öffnet `/permissions` +2. Wählt Benutzer aus +3. Klickt auf "Anpassen" +4. Setzt individuelle Berechtigungen (z.B. nur Diary-Schreibrecht) +5. Speichert + +### Szenario 3: Neues Mitglied +1. Mitglied registriert sich und fordert Zugang an +2. Admin genehmigt Anfrage (Standardrolle: "member") +3. Mitglied hat Lesezugriff +4. Bei Bedarf kann Admin die Rolle später ändern + +## Troubleshooting + +**Problem**: Berechtigungen werden nicht aktualisiert +- **Lösung**: Seite neu laden oder Club neu auswählen + +**Problem**: "Keine Berechtigung" trotz korrekter Rolle +- **Lösung**: Prüfen, ob Custom Permissions die Rolle überschreiben + +**Problem**: Owner kann keine Änderungen vornehmen +- **Lösung**: Owner sollte automatisch alle Rechte haben. Prüfen Sie die `isOwner`-Flag in der Datenbank + +## API-Endpunkte + +``` +GET /api/permissions/:clubId - Eigene Berechtigungen abrufen +GET /api/permissions/:clubId/members - Alle Mitglieder mit Berechtigungen (Admin) +PUT /api/permissions/:clubId/user/:userId/role - Rolle ändern (Admin) +PUT /api/permissions/:clubId/user/:userId/permissions - Custom Permissions setzen (Admin) +GET /api/permissions/roles/available - Verfügbare Rollen abrufen +GET /api/permissions/structure/all - Berechtigungsstruktur abrufen +``` + + diff --git a/PERMISSIONS_MIGRATION.md b/PERMISSIONS_MIGRATION.md new file mode 100644 index 0000000..08336ce --- /dev/null +++ b/PERMISSIONS_MIGRATION.md @@ -0,0 +1,235 @@ +# Berechtigungssystem - Migrations-Anleitung + +## Übersicht + +Diese Anleitung hilft Ihnen, das neue Berechtigungssystem für bestehende Clubs einzurichten. + +## Schritt 1: Datenbank-Schema erweitern + +Führen Sie zuerst die SQL-Migration aus, um die neuen Spalten hinzuzufügen: + +```bash +mysql -u username -p database_name < backend/migrations/add_permissions_to_user_club.sql +``` + +Dies fügt folgende Spalten zur `user_club` Tabelle hinzu: +- `role` (VARCHAR) - Benutzerrolle (admin, trainer, team_manager, member) +- `permissions` (JSON) - Custom Permissions +- `is_owner` (BOOLEAN) - Markiert den Club-Ersteller + +## Schritt 2: Bestehende Daten migrieren + +Sie haben zwei Optionen: + +### Option A: Node.js Script (Empfohlen) + +Das Script identifiziert automatisch den ersten Benutzer jedes Clubs (nach `createdAt`) und setzt ihn als Owner. + +```bash +cd /home/torsten/Programs/trainingstagebuch/backend +node scripts/migratePermissions.js +``` + +**Ausgabe:** +``` +Starting permissions migration... + +Found 3 club(s) + +--- Club: TTC Beispiel (ID: 1) --- + Members found: 5 + First member (will be owner): admin@example.com + ✓ Updated admin@example.com: role=admin, isOwner=true + ✓ Updated user1@example.com: role=member, isOwner=false + ✓ Updated user2@example.com: role=member, isOwner=false + ... + +✅ Migration completed successfully! + +Summary: +Club Owners (3): + - TTC Beispiel: admin@example.com + - SV Teststadt: owner@test.de + - TSC Demo: demo@example.com + +Role Distribution: + - Admins: 3 + - Members: 12 +``` + +### Option B: SQL Script + +Wenn Sie lieber SQL verwenden möchten: + +```bash +mysql -u username -p database_name < backend/migrations/update_existing_user_club_permissions.sql +``` + +Dieses Script: +1. Setzt `role = 'member'` für alle genehmigten Benutzer ohne Rolle +2. Markiert den Benutzer mit der niedrigsten `user_id` pro Club als Owner + +## Schritt 3: Manuelle Anpassungen (Optional) + +### Falscher Owner? + +Falls das Script den falschen Benutzer als Owner markiert hat, können Sie dies manuell korrigieren: + +```sql +-- Alten Owner zurücksetzen +UPDATE user_club +SET is_owner = 0, role = 'member' +WHERE club_id = 1 AND user_id = 123; + +-- Neuen Owner setzen +UPDATE user_club +SET is_owner = 1, role = 'admin' +WHERE club_id = 1 AND user_id = 456; +``` + +### Weitere Admins ernennen + +```sql +UPDATE user_club +SET role = 'admin' +WHERE club_id = 1 AND user_id = 789; +``` + +### Trainer ernennen + +```sql +UPDATE user_club +SET role = 'trainer' +WHERE club_id = 1 AND user_id = 101; +``` + +## Schritt 4: Verifizierung + +### Backend neu starten + +```bash +# Server neu starten (wenn er läuft) +sudo systemctl restart tt-tagebuch +``` + +### Im Browser testen + +1. Loggen Sie sich ein +2. Wählen Sie einen Club aus +3. Navigieren Sie zu "Berechtigungen" (nur für Admins sichtbar) +4. Überprüfen Sie, dass alle Mitglieder korrekt angezeigt werden + +### SQL Verifizierung + +```sql +-- Alle Club-Mitglieder mit ihren Berechtigungen anzeigen +SELECT + c.name as club_name, + u.email as user_email, + uc.role, + uc.is_owner, + uc.approved +FROM user_club uc +JOIN club c ON c.id = uc.club_id +JOIN user u ON u.id = uc.user_id +WHERE uc.approved = 1 +ORDER BY c.name, uc.is_owner DESC, uc.role, u.email; +``` + +## Troubleshooting + +### Problem: "Keine Berechtigung" trotz Owner-Status + +**Lösung:** Überprüfen Sie in der Datenbank: + +```sql +SELECT role, is_owner, approved +FROM user_club +WHERE user_id = YOUR_USER_ID AND club_id = YOUR_CLUB_ID; +``` + +Sollte sein: `role='admin'`, `is_owner=1`, `approved=1` + +### Problem: Owner kann nicht geändert werden + +Das ist korrekt! Der Owner (Club-Ersteller) kann seine eigenen Rechte nicht verlieren. Dies ist eine Sicherheitsmaßnahme. + +### Problem: Berechtigungen werden nicht geladen + +**Lösung:** +1. Browser-Cache leeren +2. LocalStorage leeren: `localStorage.clear()` in der Browser-Console +3. Neu einloggen + +### Problem: "Lade Mitglieder..." bleibt hängen + +**Mögliche Ursachen:** +1. Migration noch nicht ausgeführt +2. Backend nicht neu gestartet +3. Frontend nicht neu gebaut + +**Lösung:** +```bash +# Backend +cd /home/torsten/Programs/trainingstagebuch/backend +node scripts/migratePermissions.js + +# Frontend +cd /home/torsten/Programs/trainingstagebuch/frontend +npm run build + +# Server neu starten +sudo systemctl restart tt-tagebuch +``` + +## Nach der Migration + +### Neue Clubs + +Bei neuen Clubs wird der Ersteller automatisch als Owner mit Admin-Rechten eingerichtet. Keine manuelle Aktion erforderlich. + +### Neue Mitglieder + +Neue Mitglieder erhalten automatisch die Rolle "member" (Lesezugriff). Admins können die Rolle später ändern. + +### Berechtigungen verwalten + +Admins können über die Web-UI unter `/permissions` Berechtigungen verwalten: +1. Rollen zuweisen (Admin, Trainer, Mannschaftsführer, Mitglied) +2. Custom Permissions definieren (für spezielle Anwendungsfälle) + +## Wichtige Hinweise + +⚠️ **Sicherung erstellen:** +```bash +mysqldump -u username -p database_name > backup_before_permissions_$(date +%Y%m%d).sql +``` + +⚠️ **Owner-Rechte:** +- Der Owner (is_owner=1) kann nicht degradiert oder gelöscht werden +- Jeder Club hat genau einen Owner +- Owner-Rechte können nicht übertragen werden (nur durch direkte DB-Änderung) + +⚠️ **MyTischtennis:** +- MyTischtennis-Funktionen sind für ALLE Mitglieder zugänglich +- Keine Berechtigungsprüfung für MyTischtennis-Endpunkte + +## Rollback (falls nötig) + +Falls Sie das Berechtigungssystem zurücknehmen müssen: + +```sql +-- Spalten entfernen (Achtung: Datenverlust!) +ALTER TABLE user_club +DROP COLUMN role, +DROP COLUMN permissions, +DROP COLUMN is_owner; + +-- Indizes entfernen +DROP INDEX idx_user_club_role ON user_club; +DROP INDEX idx_user_club_owner ON user_club; +``` + +Dann Backend-Code auf vorherige Version zurücksetzen. + + diff --git a/backend/MYTISCHTENNIS_AUTO_FETCH_README.md b/backend/MYTISCHTENNIS_AUTO_FETCH_README.md new file mode 100644 index 0000000..bf68d3c --- /dev/null +++ b/backend/MYTISCHTENNIS_AUTO_FETCH_README.md @@ -0,0 +1,212 @@ +# MyTischtennis Automatischer Datenabruf + +## Übersicht + +Dieses System ermöglicht den automatischen Abruf von Spielergebnissen und Statistiken von myTischtennis.de. + +## Scheduler + +### 6:00 Uhr - Rating Updates +- **Service:** `autoUpdateRatingsService.js` +- **Funktion:** Aktualisiert TTR/QTTR-Werte für Spieler +- **TODO:** Implementierung der eigentlichen Rating-Update-Logik + +### 6:30 Uhr - Spielergebnisse +- **Service:** `autoFetchMatchResultsService.js` +- **Funktion:** Ruft Spielerbilanzen für konfigurierte Teams ab +- **Status:** ✅ Grundlegende Implementierung fertig + +## Benötigte Konfiguration + +### 1. MyTischtennis-Account +- Account muss in den MyTischtennis-Settings verknüpft sein +- Checkbox "Automatische Updates" aktivieren +- Passwort speichern (erforderlich für automatische Re-Authentifizierung) + +### 2. League-Konfiguration + +Für jede Liga müssen folgende Felder ausgefüllt werden: + +```sql +UPDATE league SET + my_tischtennis_group_id = '504417', -- Group ID von myTischtennis + association = 'HeTTV', -- Verband (z.B. HeTTV, DTTB) + groupname = '1.Kreisklasse' -- Gruppenname für URL +WHERE id = 1; +``` + +**Beispiel-URL:** +``` +https://www.mytischtennis.de/click-tt/HeTTV/25--26/ligen/1.Kreisklasse/gruppe/504417/... + ^^^^^ ^^^^^^^^^^^^^^ ^^^^^^ + association groupname group_id +``` + +### 3. Team-Konfiguration + +Für jedes Team muss die myTischtennis Team-ID gesetzt werden: + +```sql +UPDATE club_team SET + my_tischtennis_team_id = '2995094' -- Team ID von myTischtennis +WHERE id = 1; +``` + +**Beispiel-URL:** +``` +.../mannschaft/2995094/Harheimer_TC_(J11)/spielerbilanzen/gesamt + ^^^^^^^ + team_id +``` + +### 4. Spieler-Zuordnung (Optional) + +Spieler werden automatisch anhand des Namens zugeordnet. Für genauere Zuordnung kann die myTischtennis Player-ID gesetzt werden: + +```sql +UPDATE member SET + my_tischtennis_player_id = 'NU2705037' -- Player ID von myTischtennis +WHERE id = 1; +``` + +## Migrationen + +Folgende Migrationen müssen ausgeführt werden: + +```bash +# 1. MyTischtennis Auto-Update-Felder +mysql -u root -p trainingstagebuch < backend/migrations/add_auto_update_ratings_to_my_tischtennis.sql + +# 2. MyTischtennis Update-History-Tabelle +mysql -u root -p trainingstagebuch < backend/migrations/create_my_tischtennis_update_history.sql + +# 3. League MyTischtennis-Felder +mysql -u root -p trainingstagebuch < backend/migrations/add_mytischtennis_fields_to_league.sql + +# 4. Team MyTischtennis-ID +mysql -u root -p trainingstagebuch < backend/migrations/add_mytischtennis_team_id_to_club_team.sql + +# 5. Member MyTischtennis Player-ID +mysql -u root -p trainingstagebuch < backend/migrations/add_mytischtennis_player_id_to_member.sql + +# 6. Match Result-Felder +mysql -u root -p trainingstagebuch < backend/migrations/add_match_result_fields.sql +``` + +## Abgerufene Daten + +Von der myTischtennis API werden folgende Daten abgerufen: + +### Einzelstatistiken +- Player ID, Vorname, Nachname +- Gewonnene/Verlorene Punkte +- Anzahl Spiele +- Detaillierte Statistiken nach Gegner-Position + +### Doppelstatistiken +- Player IDs, Namen der beiden Spieler +- Gewonnene/Verlorene Punkte +- Anzahl Spiele + +### Team-Informationen +- Teamname, Liga, Saison +- Gesamtpunkte (gewonnen/verloren) +- Doppel- und Einzelpunkte + +## Implementierungsdetails + +### Datenfluss + +1. **Scheduler** (6:30 Uhr): + - `schedulerService.js` triggert `autoFetchMatchResultsService.executeAutomaticFetch()` + +2. **Account-Verarbeitung**: + - Lädt alle MyTischtennis-Accounts mit `autoUpdateRatings = true` + - Prüft Session-Gültigkeit + - Re-Authentifizierung bei abgelaufener Session + +3. **Team-Abfrage**: + - Lädt alle Teams mit konfigurierten myTischtennis-IDs + - Baut API-URL dynamisch zusammen + - Führt authentifizierten GET-Request durch + +4. **Datenverarbeitung**: + - Parst JSON-Response + - Matched Spieler anhand von ID oder Name + - Speichert myTischtennis Player-ID bei Mitgliedern + - Loggt Statistiken + +### Player-Matching-Algorithmus + +```javascript +1. Suche nach myTischtennis Player-ID (exakte Übereinstimmung) +2. Falls nicht gefunden: Suche nach Name (case-insensitive) +3. Falls gefunden: Speichere myTischtennis Player-ID für zukünftige Abfragen +``` + +**Hinweis:** Da Namen verschlüsselt gespeichert werden, müssen für den Namens-Abgleich alle Members geladen und entschlüsselt werden. Dies ist bei großen Datenbanken ineffizient. + +## TODO / Offene Punkte + +### Noch zu implementieren: + +1. **TTR/QTTR Updates** (6:00 Uhr Job): + - Endpoint für TTR/QTTR-Daten identifizieren + - Daten abrufen und in Member-Tabelle speichern + +2. **Spielergebnis-Details**: + - Einzelne Matches mit Satzständen speichern + - Tabelle für Match-Historie erstellen + +3. **History-Tabelle für Spielergebnis-Abrufe** (optional): + - Ähnlich zu `my_tischtennis_update_history` + - Speichert Erfolg/Fehler der Abrufe + +4. **Benachrichtigungen** (optional): + - Email/Push bei neuen Ergebnissen + - Highlights für besondere Siege + +5. **Performance-Optimierung**: + - Caching für Player-Matches + - Incremental Updates (nur neue Daten) + +## Manueller Test + +```javascript +// Im Node-Backend-Code oder über API-Endpoint: +import schedulerService from './services/schedulerService.js'; + +// Rating Updates manuell triggern +await schedulerService.triggerRatingUpdates(); + +// Spielergebnisse manuell abrufen +await schedulerService.triggerMatchResultsFetch(); +``` + +## API-Dokumentation + +### MyTischtennis Spielerbilanzen-Endpoint + +**URL-Format:** +``` +https://www.mytischtennis.de/click-tt/{association}/{season}/ligen/{groupname}/gruppe/{groupId}/mannschaft/{teamId}/{teamname}/spielerbilanzen/gesamt?_data=routes%2Fclick-tt%2B%2F%24association%2B%2F%24season%2B%2F%24type%2B%2F%28%24groupname%29.gruppe.%24urlid_.mannschaft.%24teamid.%24teamname%2B%2Fspielerbilanzen.%24filter +``` + +**Parameter:** +- `{association}`: Verband (z.B. "HeTTV") +- `{season}`: Saison im Format "25--26" +- `{groupname}`: Gruppenname URL-encoded (z.B. "1.Kreisklasse") +- `{groupId}`: Gruppen-ID (numerisch, z.B. "504417") +- `{teamId}`: Team-ID (numerisch, z.B. "2995094") +- `{teamname}`: Teamname URL-encoded mit Underscores (z.B. "Harheimer_TC_(J11)") + +**Response:** JSON mit `data.balancesheet` Array + +## Sicherheit + +- ✅ Automatische Session-Verwaltung +- ✅ Re-Authentifizierung bei abgelaufenen Sessions +- ✅ Passwörter verschlüsselt gespeichert +- ✅ Fehlerbehandlung und Logging +- ✅ Graceful Degradation (einzelne Team-Fehler stoppen nicht den gesamten Prozess) + diff --git a/backend/MYTISCHTENNIS_URL_PARSER_README.md b/backend/MYTISCHTENNIS_URL_PARSER_README.md new file mode 100644 index 0000000..2b006bb --- /dev/null +++ b/backend/MYTISCHTENNIS_URL_PARSER_README.md @@ -0,0 +1,332 @@ +# MyTischtennis URL Parser + +## Übersicht + +Der URL-Parser ermöglicht es, myTischtennis-Team-URLs automatisch zu parsen und die Konfiguration für automatische Datenabrufe vorzunehmen. + +## Verwendung + +### 1. URL Parsen + +**Endpoint:** `POST /api/mytischtennis/parse-url` + +**Request:** +```json +{ + "url": "https://www.mytischtennis.de/click-tt/HeTTV/25--26/ligen/1.Kreisklasse/gruppe/504417/mannschaft/2995094/Harheimer_TC_(J11)/spielerbilanzen/gesamt" +} +``` + +**Response:** +```json +{ + "success": true, + "data": { + "association": "HeTTV", + "season": "25/26", + "type": "ligen", + "groupname": "1.Kreisklasse", + "groupId": "504417", + "teamId": "2995094", + "teamname": "Harheimer TC (J11)", + "originalUrl": "https://www.mytischtennis.de/click-tt/...", + "clubId": "43030", + "clubName": "Harheimer TC", + "teamName": "Jugend 11", + "leagueName": "Jugend 13 1. Kreisklasse", + "region": "Frankfurt", + "tableRank": 8, + "matchesWon": 0, + "matchesLost": 3 + } +} +``` + +### 2. Team Automatisch Konfigurieren + +**Endpoint:** `POST /api/mytischtennis/configure-team` + +**Request:** +```json +{ + "url": "https://www.mytischtennis.de/click-tt/HeTTV/25--26/ligen/1.Kreisklasse/gruppe/504417/mannschaft/2995094/Harheimer_TC_(J11)/spielerbilanzen/gesamt", + "clubTeamId": 1, + "createLeague": false, + "createSeason": false +} +``` + +**Parameter:** +- `url` (required): Die myTischtennis-URL +- `clubTeamId` (required): Die ID des lokalen Club-Teams +- `createLeague` (optional): Wenn `true`, wird eine neue League erstellt +- `createSeason` (optional): Wenn `true`, wird eine neue Season erstellt + +**Response:** +```json +{ + "success": true, + "message": "Team configured successfully", + "data": { + "team": { + "id": 1, + "name": "Jugend 11", + "myTischtennisTeamId": "2995094" + }, + "league": { + "id": 5, + "name": "Jugend 13 1. Kreisklasse", + "myTischtennisGroupId": "504417", + "association": "HeTTV", + "groupname": "1.Kreisklasse" + }, + "season": { + "id": 2, + "name": "25/26" + }, + "parsedData": { ... } + } +} +``` + +### 3. URL für Team Abrufen + +**Endpoint:** `GET /api/mytischtennis/team-url/:teamId` + +**Response:** +```json +{ + "success": true, + "url": "https://www.mytischtennis.de/click-tt/HeTTV/25--26/ligen/1.Kreisklasse/gruppe/504417/mannschaft/2995094/Harheimer%20TC%20%28J11%29/spielerbilanzen/gesamt" +} +``` + +## URL-Format + +### Unterstützte URL-Muster + +``` +https://www.mytischtennis.de/click-tt/{association}/{season}/{type}/{groupname}/gruppe/{groupId}/mannschaft/{teamId}/{teamname}/... +``` + +**Komponenten:** +- `{association}`: Verband (z.B. "HeTTV", "DTTB", "WestD") +- `{season}`: Saison im Format "YY--YY" (z.B. "25--26" für 2025/2026) +- `{type}`: Typ (meist "ligen") +- `{groupname}`: Gruppenname URL-encoded (z.B. "1.Kreisklasse", "Kreisliga") +- `{groupId}`: Numerische Gruppen-ID (z.B. "504417") +- `{teamId}`: Numerische Team-ID (z.B. "2995094") +- `{teamname}`: Teamname URL-encoded mit Underscores (z.B. "Harheimer_TC_(J11)") + +### Beispiel-URLs + +**Spielerbilanzen:** +``` +https://www.mytischtennis.de/click-tt/HeTTV/25--26/ligen/1.Kreisklasse/gruppe/504417/mannschaft/2995094/Harheimer_TC_(J11)/spielerbilanzen/gesamt +``` + +**Spielplan:** +``` +https://www.mytischtennis.de/click-tt/HeTTV/25--26/ligen/1.Kreisklasse/gruppe/504417/mannschaft/2995094/Harheimer_TC_(J11)/spielplan +``` + +**Tabelle:** +``` +https://www.mytischtennis.de/click-tt/HeTTV/25--26/ligen/1.Kreisklasse/gruppe/504417/mannschaft/2995094/Harheimer_TC_(J11)/tabelle +``` + +## Datenfluss + +### Ohne MyTischtennis-Login + +1. URL wird geparst +2. Nur URL-Komponenten werden extrahiert +3. Zusätzliche Daten (clubName, leagueName, etc.) sind nicht verfügbar + +### Mit MyTischtennis-Login + +1. URL wird geparst +2. API-Request an myTischtennis mit Authentication +3. Vollständige Team-Daten werden abgerufen +4. Alle Felder sind verfügbar + +## Frontend-Integration + +### Vue.js Beispiel + +```javascript + + + + + + {{ parsedData.teamname }} + Liga: {{ parsedData.leagueName }} + Verband: {{ parsedData.association }} + Tabelle: Platz {{ parsedData.tableRank }} + + Team konfigurieren + + + + + +``` + +## Workflow + +### Empfohlener Workflow für Benutzer + +1. **MyTischtennis-URL kopieren:** + - Auf myTischtennis.de zum Team navigieren + - URL aus Adresszeile kopieren + +2. **URL in Trainingstagebuch einfügen:** + - Zu Team-Verwaltung navigieren + - URL einfügen + - Automatisches Parsen + +3. **Konfiguration überprüfen:** + - Geparste Daten werden angezeigt + - Benutzer kann Daten überprüfen und bei Bedarf anpassen + +4. **Team konfigurieren:** + - Auf "Konfigurieren" klicken + - System speichert alle benötigten IDs + - Automatischer Datenabruf ist ab sofort aktiv + +## Fehlerbehandlung + +### Häufige Fehler + +**"Invalid myTischtennis URL format"** +- URL entspricht nicht dem erwarteten Format +- Lösung: Vollständige URL von der Spielerbilanzen-Seite kopieren + +**"Season not found"** +- Saison existiert noch nicht in der Datenbank +- Lösung: `createSeason: true` setzen + +**"Team has no league assigned"** +- Team hat keine verknüpfte Liga +- Lösung: `createLeague: true` setzen oder Liga manuell zuweisen + +**"HTTP 401: Unauthorized"** +- MyTischtennis-Login abgelaufen oder nicht vorhanden +- Lösung: In MyTischtennis-Settings erneut anmelden + +## Sicherheit + +- ✅ Alle Endpoints erfordern Authentifizierung +- ✅ UserID wird aus Header-Parameter gelesen +- ✅ MyTischtennis-Credentials werden sicher gespeichert +- ✅ Keine sensiblen Daten in URLs + +## Technische Details + +### Service: `myTischtennisUrlParserService` + +**Methoden:** +- `parseUrl(url)` - Parst URL und extrahiert Komponenten +- `fetchTeamData(parsedUrl, cookie, accessToken)` - Ruft zusätzliche Daten ab +- `getCompleteConfig(url, cookie, accessToken)` - Kombination aus Parsen + Abrufen +- `isValidTeamUrl(url)` - Validiert URL-Format +- `buildUrl(config)` - Baut URL aus Komponenten + +### Controller: `myTischtennisUrlController` + +**Endpoints:** +- `POST /api/mytischtennis/parse-url` - URL parsen +- `POST /api/mytischtennis/configure-team` - Team konfigurieren +- `GET /api/mytischtennis/team-url/:teamId` - URL abrufen + +## Zukünftige Erweiterungen + +### Geplante Features + +1. **Bulk-Import:** + - Mehrere URLs gleichzeitig importieren + - Alle Teams einer Liga auf einmal konfigurieren + +2. **Auto-Discovery:** + - Automatisches Finden aller Teams eines Vereins + - Vorschläge für ähnliche Teams + +3. **Validierung:** + - Prüfung, ob Team bereits konfiguriert ist + - Warnung bei Duplikaten + +4. **History:** + - Speichern der URL-Konfigurationen + - Versionierung bei Änderungen + diff --git a/backend/cleanupKeysNode.cjs b/backend/cleanupKeysNode.cjs index 279c213..f9d65ec 100644 --- a/backend/cleanupKeysNode.cjs +++ b/backend/cleanupKeysNode.cjs @@ -9,15 +9,18 @@ const dbConfig = { database: process.env.DB_NAME || 'trainingsdiary' }; +const report = []; + async function cleanupKeys() { let connection; try { - console.log('🔌 Verbinde mit der Datenbank...'); + report.push('🔌 Verbinde mit der Datenbank...'); connection = await mysql.createConnection(dbConfig); // 1. Status vor dem Cleanup - console.log('\n📊 STATUS VOR DEM CLEANUP:'); + report.push(''); + report.push('📊 STATUS VOR DEM CLEANUP:'); const [tablesBefore] = await connection.execute(` SELECT TABLE_NAME, @@ -29,57 +32,60 @@ async function cleanupKeys() { `, [dbConfig.database]); tablesBefore.forEach(table => { - console.log(` ${table.TABLE_NAME}: ${table.key_count} Keys`); + report.push(` ${table.TABLE_NAME}: ${table.key_count} Keys`); }); // 2. Alle INDEX der Problem-Tabellen anzeigen const problemTables = ['member', 'diary_tags', 'season']; for (const tableName of problemTables) { - console.log(`\n🔍 INDEX für Tabelle '${tableName}':`); + report.push(''); + report.push(`🔍 INDEX für Tabelle '${tableName}':`); try { const [indexes] = await connection.execute(`SHOW INDEX FROM \`${tableName}\``); if (indexes.length === 0) { - console.log(` Keine INDEX gefunden für Tabelle '${tableName}'`); + report.push(` Keine INDEX gefunden für Tabelle '${tableName}'`); continue; } indexes.forEach(index => { - console.log(` - ${index.Key_name} (${index.Column_name}) - ${index.Non_unique === 0 ? 'UNIQUE' : 'NON-UNIQUE'}`); + report.push(` - ${index.Key_name} (${index.Column_name}) - ${index.Non_unique === 0 ? 'UNIQUE' : 'NON-UNIQUE'}`); }); // 3. Überflüssige INDEX entfernen (alle außer PRIMARY und UNIQUE) - console.log(`\n🗑️ Entferne überflüssige INDEX aus '${tableName}':`); + report.push(''); + report.push(`🗑️ Entferne überflüssige INDEX aus '${tableName}':`); for (const index of indexes) { // Behalte PRIMARY KEY und UNIQUE constraints if (index.Key_name === 'PRIMARY' || index.Non_unique === 0) { - console.log(` ✅ Behalte: ${index.Key_name} (${index.Column_name})`); + report.push(` ✅ Behalte: ${index.Key_name} (${index.Column_name})`); continue; } // Entferne alle anderen INDEX try { await connection.execute(`DROP INDEX \`${index.Key_name}\` ON \`${tableName}\``); - console.log(` ❌ Entfernt: ${index.Key_name} (${index.Column_name})`); + report.push(` ❌ Entfernt: ${index.Key_name} (${index.Column_name})`); } catch (error) { if (error.code === 'ER_CANT_DROP_FIELD_OR_KEY') { - console.log(` ⚠️ Kann nicht entfernen: ${index.Key_name} (${index.Column_name}) - ${error.message}`); + report.push(` ⚠️ Kann nicht entfernen: ${index.Key_name} (${index.Column_name}) - ${error.message}`); } else { - console.log(` ❌ Fehler beim Entfernen von ${index.Key_name}: ${error.message}`); + report.push(` ❌ Fehler beim Entfernen von ${index.Key_name}: ${error.message}`); } } } } catch (error) { - console.log(` ⚠️ Fehler beim Zugriff auf Tabelle '${tableName}': ${error.message}`); + report.push(` ⚠️ Fehler beim Zugriff auf Tabelle '${tableName}': ${error.message}`); } } // 4. Status nach dem Cleanup - console.log('\n📊 STATUS NACH DEM CLEANUP:'); + report.push(''); + report.push('📊 STATUS NACH DEM CLEANUP:'); const [tablesAfter] = await connection.execute(` SELECT TABLE_NAME, @@ -96,7 +102,7 @@ async function cleanupKeys() { const diff = beforeCount - table.key_count; const status = table.key_count <= 5 ? '✅' : table.key_count <= 10 ? '⚠️' : '❌'; - console.log(` ${status} ${table.TABLE_NAME}: ${table.key_count} Keys (${diff > 0 ? `-${diff}` : `+${Math.abs(diff)}`})`); + report.push(` ${status} ${table.TABLE_NAME}: ${table.key_count} Keys (${diff > 0 ? `-${diff}` : `+${Math.abs(diff)}`})`); }); // 5. Gesamtanzahl der Keys @@ -106,18 +112,20 @@ async function cleanupKeys() { WHERE TABLE_SCHEMA = ? `, [dbConfig.database]); - console.log(`\n📈 GESAMTANZAHL KEYS: ${totalKeys[0].total_keys}`); - + report.push(''); + report.push(`📈 GESAMTANZAHL KEYS: ${totalKeys[0].total_keys}`); + // 6. Zusammenfassung - console.log('\n🎯 ZUSAMMENFASSUNG:'); + report.push(''); + report.push('🎯 ZUSAMMENFASSUNG:'); const problemTablesAfter = tablesAfter.filter(t => t.key_count > 10); if (problemTablesAfter.length === 0) { - console.log(' ✅ Alle Tabellen haben jetzt weniger als 10 Keys!'); + report.push(' ✅ Alle Tabellen haben jetzt weniger als 10 Keys!'); } else { - console.log(' ⚠️ Folgende Tabellen haben immer noch zu viele Keys:'); + report.push(' ⚠️ Folgende Tabellen haben immer noch zu viele Keys:'); problemTablesAfter.forEach(table => { - console.log(` - ${table.TABLE_NAME}: ${table.key_count} Keys`); + report.push(` - ${table.TABLE_NAME}: ${table.key_count} Keys`); }); } @@ -126,15 +134,18 @@ async function cleanupKeys() { } finally { if (connection) { await connection.end(); - console.log('\n🔌 Datenbankverbindung geschlossen.'); + report.push(''); + report.push('🔌 Datenbankverbindung geschlossen.'); } } } // Script ausführen -console.log('🚀 Starte intelligentes INDEX-Cleanup...\n'); +report.push('🚀 Starte intelligentes INDEX-Cleanup...'); cleanupKeys().then(() => { - console.log('\n✨ Cleanup abgeschlossen!'); + report.push(''); + report.push('✨ Cleanup abgeschlossen!'); + process.stdout.write(`${report.join('\n')}\n`); process.exit(0); }).catch(error => { console.error('\n💥 Fehler beim Cleanup:', error); diff --git a/backend/cleanupKeysNode.js b/backend/cleanupKeysNode.js index 031a000..8783865 100644 --- a/backend/cleanupKeysNode.js +++ b/backend/cleanupKeysNode.js @@ -7,41 +7,23 @@ import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); +const report = []; + // Umgebungsvariablen aus dem Root-Verzeichnis laden -//const envPath = path.join(__dirname, '..', '.env'); -//console.log('🔍 Lade .env-Datei von:', envPath); +const envPath = path.join(__dirname, '..', '.env'); dotenv.config(); - -// Debug: Zeige geladene Umgebungsvariablen -console.log('🔍 Geladene Umgebungsvariablen:'); -console.log(' DB_HOST:', process.env.DB_HOST); -console.log(' DB_USER:', process.env.DB_USER); -console.log(' DB_NAME:', process.env.DB_NAME); -console.log(' DB_PASSWORD:', process.env.DB_PASSWORD ? '***gesetzt***' : 'nicht gesetzt'); - -// Datenbankverbindung -const dbConfig = { - host: process.env.DB_HOST || 'localhost', - user: process.env.DB_USER || 'root', - password: process.env.DB_PASSWORD || '', - database: process.env.DB_NAME || 'trainingsdiary' -}; - -console.log('🔍 Datenbankverbindung:'); -console.log(' Host:', dbConfig.host); -console.log(' User:', dbConfig.user); -console.log(' Database:', dbConfig.database); -console.log(' Password:', dbConfig.password ? '***gesetzt***' : 'nicht gesetzt'); +report.push('Environment variables loaded'); async function cleanupKeys() { let connection; try { - console.log('🔌 Verbinde mit der Datenbank...'); + report.push('🔌 Verbinde mit der Datenbank...'); connection = await mysql.createConnection(dbConfig); // 1. Status vor dem Cleanup - console.log('\n📊 STATUS VOR DEM CLEANUP:'); + report.push(''); + report.push('📊 STATUS VOR DEM CLEANUP:'); const [tablesBefore] = await connection.execute(` SELECT TABLE_NAME, @@ -53,57 +35,60 @@ async function cleanupKeys() { `, [dbConfig.database]); tablesBefore.forEach(table => { - console.log(` ${table.TABLE_NAME}: ${table.key_count} Keys`); + report.push(` ${table.TABLE_NAME}: ${table.key_count} Keys`); }); // 2. Alle INDEX der Problem-Tabellen anzeigen const problemTables = ['member', 'diary_tags', 'season']; for (const tableName of problemTables) { - console.log(`\n🔍 INDEX für Tabelle '${tableName}':`); + report.push(''); + report.push(`🔍 INDEX für Tabelle '${tableName}':`); try { const [indexes] = await connection.execute(`SHOW INDEX FROM \`${tableName}\``); if (indexes.length === 0) { - console.log(` Keine INDEX gefunden für Tabelle '${tableName}'`); + report.push(` Keine INDEX gefunden für Tabelle '${tableName}'`); continue; } indexes.forEach(index => { - console.log(` - ${index.Key_name} (${index.Column_name}) - ${index.Non_unique === 0 ? 'UNIQUE' : 'NON-UNIQUE'}`); + report.push(` - ${index.Key_name} (${index.Column_name}) - ${index.Non_unique === 0 ? 'UNIQUE' : 'NON-UNIQUE'}`); }); // 3. Überflüssige INDEX entfernen (alle außer PRIMARY und UNIQUE) - console.log(`\n🗑️ Entferne überflüssige INDEX aus '${tableName}':`); + report.push(''); + report.push(`🗑️ Entferne überflüssige INDEX aus '${tableName}':`); for (const index of indexes) { // Behalte PRIMARY KEY und UNIQUE constraints if (index.Key_name === 'PRIMARY' || index.Non_unique === 0) { - console.log(` ✅ Behalte: ${index.Key_name} (${index.Column_name})`); + report.push(` ✅ Behalte: ${index.Key_name} (${index.Column_name})`); continue; } // Entferne alle anderen INDEX try { await connection.execute(`DROP INDEX \`${index.Key_name}\` ON \`${tableName}\``); - console.log(` ❌ Entfernt: ${index.Key_name} (${index.Column_name})`); + report.push(` ❌ Entfernt: ${index.Key_name} (${index.Column_name})`); } catch (error) { if (error.code === 'ER_CANT_DROP_FIELD_OR_KEY') { - console.log(` ⚠️ Kann nicht entfernen: ${index.Key_name} (${index.Column_name}) - ${error.message}`); + report.push(` ⚠️ Kann nicht entfernen: ${index.Key_name} (${index.Column_name}) - ${error.message}`); } else { - console.log(` ❌ Fehler beim Entfernen von ${index.Key_name}: ${error.message}`); + report.push(` ❌ Fehler beim Entfernen von ${index.Key_name}: ${error.message}`); } } } } catch (error) { - console.log(` ⚠️ Fehler beim Zugriff auf Tabelle '${tableName}': ${error.message}`); + report.push(` ⚠️ Fehler beim Zugriff auf Tabelle '${tableName}': ${error.message}`); } } // 4. Status nach dem Cleanup - console.log('\n📊 STATUS NACH DEM CLEANUP:'); + report.push(''); + report.push('📊 STATUS NACH DEM CLEANUP:'); const [tablesAfter] = await connection.execute(` SELECT TABLE_NAME, @@ -120,7 +105,7 @@ async function cleanupKeys() { const diff = beforeCount - table.key_count; const status = table.key_count <= 5 ? '✅' : table.key_count <= 10 ? '⚠️' : '❌'; - console.log(` ${status} ${table.TABLE_NAME}: ${table.key_count} Keys (${diff > 0 ? `-${diff}` : `+${Math.abs(diff)}`})`); + report.push(` ${status} ${table.TABLE_NAME}: ${table.key_count} Keys (${diff > 0 ? `-${diff}` : `+${Math.abs(diff)}`})`); }); // 5. Gesamtanzahl der Keys @@ -130,18 +115,20 @@ async function cleanupKeys() { WHERE TABLE_SCHEMA = ? `, [dbConfig.database]); - console.log(`\n📈 GESAMTANZAHL KEYS: ${totalKeys[0].total_keys}`); + report.push(''); + report.push(`📈 GESAMTANZAHL KEYS: ${totalKeys[0].total_keys}`); // 6. Zusammenfassung - console.log('\n🎯 ZUSAMMENFASSUNG:'); + report.push(''); + report.push('🎯 ZUSAMMENFASSUNG:'); const problemTablesAfter = tablesAfter.filter(t => t.key_count > 10); if (problemTablesAfter.length === 0) { - console.log(' ✅ Alle Tabellen haben jetzt weniger als 10 Keys!'); + report.push(' ✅ Alle Tabellen haben jetzt weniger als 10 Keys!'); } else { - console.log(' ⚠️ Folgende Tabellen haben immer noch zu viele Keys:'); + report.push(' ⚠️ Folgende Tabellen haben immer noch zu viele Keys:'); problemTablesAfter.forEach(table => { - console.log(` - ${table.TABLE_NAME}: ${table.key_count} Keys`); + report.push(` - ${table.TABLE_NAME}: ${table.key_count} Keys`); }); } @@ -150,15 +137,18 @@ async function cleanupKeys() { } finally { if (connection) { await connection.end(); - console.log('\n🔌 Datenbankverbindung geschlossen.'); + report.push(''); + report.push('🔌 Datenbankverbindung geschlossen.'); } } } // Script ausführen -console.log('🚀 Starte intelligentes INDEX-Cleanup...\n'); +report.push('🚀 Starte intelligentes INDEX-Cleanup...'); cleanupKeys().then(() => { - console.log('\n✨ Cleanup abgeschlossen!'); + report.push(''); + report.push('✨ Cleanup abgeschlossen!'); + process.stdout.write(`${report.join('\n')}\n`); process.exit(0); }).catch(error => { console.error('\n💥 Fehler beim Cleanup:', error); diff --git a/backend/clients/myTischtennisClient.js b/backend/clients/myTischtennisClient.js index a7d9ad4..1af6b69 100644 --- a/backend/clients/myTischtennisClient.js +++ b/backend/clients/myTischtennisClient.js @@ -156,17 +156,6 @@ class MyTischtennisClient { if (result.success) { - console.log('[getUserProfile] - Response structure:', { - hasUserProfile: !!result.data?.userProfile, - hasClub: !!result.data?.userProfile?.club, - hasOrganization: !!result.data?.userProfile?.organization, - clubnr: result.data?.userProfile?.club?.clubnr, - clubName: result.data?.userProfile?.club?.name, - orgShort: result.data?.userProfile?.organization?.short, - ttr: result.data?.userProfile?.ttr, - qttr: result.data?.userProfile?.qttr - }); - return { success: true, @@ -190,14 +179,14 @@ class MyTischtennisClient { * @param {string} fedNickname - Federation nickname (e.g., "HeTTV") * @returns {Promise} Rankings with player entries (all pages) */ - async getClubRankings(cookie, clubId, fedNickname) { + async getClubRankings(cookie, clubId, fedNickname, currentRanking = 'yes') { const allEntries = []; let currentPage = 0; let hasMorePages = true; while (hasMorePages) { - const endpoint = `/rankings/andro-rangliste?all-players=on&clubnr=${clubId}&fednickname=${fedNickname}&results-per-page=100&page=${currentPage}&_data=routes%2F%24`; + const endpoint = `/rankings/andro-rangliste?all-players=on&clubnr=${clubId}&fednickname=${fedNickname}¤t-ranking=${currentRanking}&results-per-page=100&page=${currentPage}&_data=routes%2F%24`; const result = await this.authenticatedRequest(endpoint, cookie, { diff --git a/backend/config.js b/backend/config.js index 3910300..9af4f2e 100644 --- a/backend/config.js +++ b/backend/config.js @@ -1,17 +1,41 @@ import dotenv from 'dotenv'; +import path from 'path'; +import { fileURLToPath } from 'url'; -dotenv.config(); +// Ensure .env is loaded from the backend folder (not dependent on process.cwd()) +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +dotenv.config({ path: path.resolve(__dirname, '.env') }); -export const development = { +const isTestEnv = process.env.NODE_ENV === 'test'; + +const baseConfig = { username: process.env.DB_USER || 'root', password: process.env.DB_PASSWORD || 'hitomisan', database: process.env.DB_NAME || 'trainingdiary', - host: process.env.DB_HOST, - dialect: process.env.DB_DIALECT, + host: process.env.DB_HOST || 'localhost', + dialect: process.env.DB_DIALECT || 'mysql', define: { freezeTableName: true, underscored: true, underscoredAll: true, }, + logging: false, + storage: process.env.DB_STORAGE, }; + +if (isTestEnv) { + baseConfig.username = 'sqlite'; + baseConfig.password = ''; + baseConfig.database = 'sqlite'; + baseConfig.host = 'localhost'; + baseConfig.dialect = 'sqlite'; + baseConfig.storage = process.env.DB_STORAGE || ':memory:'; +} + +if (baseConfig.dialect === 'sqlite' && !baseConfig.storage) { + baseConfig.storage = ':memory:'; +} + +export const development = baseConfig; \ No newline at end of file diff --git a/backend/controllers/apiLogController.js b/backend/controllers/apiLogController.js new file mode 100644 index 0000000..86713df --- /dev/null +++ b/backend/controllers/apiLogController.js @@ -0,0 +1,85 @@ +import apiLogService from '../services/apiLogService.js'; +import HttpError from '../exceptions/HttpError.js'; + +class ApiLogController { + /** + * GET /api/logs + * Get API logs with optional filters + */ + async getLogs(req, res, next) { + try { + const { + userId, + logType, + method, + path, + statusCode, + startDate, + endDate, + limit = 100, + offset = 0 + } = req.query; + + const result = await apiLogService.getLogs({ + userId: userId ? parseInt(userId) : null, + logType, + method, + path, + statusCode: statusCode ? parseInt(statusCode) : null, + startDate, + endDate, + limit: parseInt(limit), + offset: parseInt(offset) + }); + + res.json({ + success: true, + data: result + }); + } catch (error) { + next(error); + } + } + + /** + * GET /api/logs/:id + * Get a single log entry by ID + */ + async getLogById(req, res, next) { + try { + const { id } = req.params; + const log = await apiLogService.getLogById(parseInt(id)); + + if (!log) { + throw new HttpError('Log entry not found', 404); + } + + res.json({ + success: true, + data: log + }); + } catch (error) { + next(error); + } + } + + /** + * GET /api/logs/scheduler/last-executions + * Get last execution info for scheduler jobs + */ + async getLastSchedulerExecutions(req, res, next) { + try { + const { clubId } = req.query; + const results = await apiLogService.getLastSchedulerExecutions(clubId ? parseInt(clubId) : null); + res.json({ + success: true, + data: results + }); + } catch (error) { + next(error); + } + } +} + +export default new ApiLogController(); + diff --git a/backend/controllers/clubsController.js b/backend/controllers/clubsController.js index 900d0a0..9ce43a5 100644 --- a/backend/controllers/clubsController.js +++ b/backend/controllers/clubsController.js @@ -25,7 +25,7 @@ export const addClub = async (req, res) => { } const newClub = await ClubService.createClub(clubName); - await ClubService.addUserToClub(user.id, newClub.id); + await ClubService.addUserToClub(user.id, newClub.id, true); // true = isOwner res.status(200).json(newClub); } catch (error) { console.error('[addClub] - error:', error); diff --git a/backend/controllers/diaryDateActivityController.js b/backend/controllers/diaryDateActivityController.js index 3802a47..d617b5d 100644 --- a/backend/controllers/diaryDateActivityController.js +++ b/backend/controllers/diaryDateActivityController.js @@ -79,11 +79,23 @@ export const getDiaryDateActivities = async (req, res) => { export const addGroupActivity = async(req, res) => { try { const { authcode: userToken } = req.headers; - const { clubId, diaryDateId, groupId, activity } = req.body; - const activityItem = await diaryDateActivityService.addGroupActivity(userToken, clubId, diaryDateId, groupId, activity); + const { clubId, diaryDateId, groupId, activity, timeblockId } = req.body; + const activityItem = await diaryDateActivityService.addGroupActivity(userToken, clubId, diaryDateId, groupId, activity, timeblockId); res.status(201).json(activityItem); } catch (error) { devLog(error); res.status(500).json({ error: 'Error adding group activity' }); } +} + +export const deleteGroupActivity = async(req, res) => { + try { + const { authcode: userToken } = req.headers; + const { clubId, groupActivityId } = req.params; + await diaryDateActivityService.deleteGroupActivity(userToken, clubId, groupActivityId); + res.status(200).json({ message: 'Group activity deleted' }); + } catch (error) { + devLog(error); + res.status(500).json({ error: 'Error deleting group activity' }); + } } \ No newline at end of file diff --git a/backend/controllers/diaryMemberActivityController.js b/backend/controllers/diaryMemberActivityController.js index b47a3bd..7f96a50 100644 --- a/backend/controllers/diaryMemberActivityController.js +++ b/backend/controllers/diaryMemberActivityController.js @@ -19,20 +19,32 @@ export const addMembersToActivity = async (req, res) => { const { authcode: userToken } = req.headers; const { clubId, diaryDateActivityId } = req.params; const { participantIds } = req.body; // array of participant ids + await checkAccess(userToken, clubId); + + if (!participantIds || !Array.isArray(participantIds)) { + console.error('[addMembersToActivity] Invalid participantIds:', participantIds); + return res.status(400).json({ error: 'participantIds must be an array' }); + } + const validParticipants = await Participant.findAll({ where: { id: participantIds } }); + const validIds = new Set(validParticipants.map(p => p.id)); const created = []; for (const pid of participantIds) { - if (!validIds.has(pid)) continue; + if (!validIds.has(pid)) { + continue; + } const existing = await DiaryMemberActivity.findOne({ where: { diaryDateActivityId, participantId: pid } }); if (!existing) { const rec = await DiaryMemberActivity.create({ diaryDateActivityId, participantId: pid }); created.push(rec); + } else { } } res.status(201).json(created); } catch (e) { + console.error('[addMembersToActivity] Error:', e); res.status(500).json({ error: 'Error adding members to activity' }); } }; diff --git a/backend/controllers/diaryNoteController.js b/backend/controllers/diaryNoteController.js index dee309c..1e7dec1 100644 --- a/backend/controllers/diaryNoteController.js +++ b/backend/controllers/diaryNoteController.js @@ -18,17 +18,28 @@ export const getNotes = async (req, res) => { export const createNote = async (req, res) => { try { - const { memberId, content, tags } = req.body; - const newNote = await DiaryNote.create({ memberId, content }); - if (tags && tags.length > 0) { + const { memberId, diaryDateId, content, tags } = req.body; + + if (!memberId || !diaryDateId || !content) { + return res.status(400).json({ error: 'memberId, diaryDateId und content sind erforderlich.' }); + } + + const newNote = await DiaryNote.create({ memberId, diaryDateId, content }); + + if (Array.isArray(tags) && tags.length > 0 && typeof newNote.addTags === 'function') { const tagInstances = await DiaryTag.findAll({ where: { id: tags } }); await newNote.addTags(tagInstances); + + const noteWithTags = await DiaryNote.findByPk(newNote.id, { + include: [{ model: DiaryTag, as: 'tags', required: false }], + }); + + return res.status(201).json(noteWithTags ?? newNote); } - const noteWithTags = await DiaryNote.findByPk(newNote.id, { - include: [{ model: DiaryTag, as: 'tags' }], - }); - res.status(201).json(noteWithTags); + + res.status(201).json(newNote); } catch (error) { + console.error('[createNote] - Error:', error); res.status(500).json({ error: 'Error creating note' }); } }; diff --git a/backend/controllers/diaryTagController.js b/backend/controllers/diaryTagController.js index 422e6b7..c0249d5 100644 --- a/backend/controllers/diaryTagController.js +++ b/backend/controllers/diaryTagController.js @@ -1,6 +1,5 @@ import { DiaryTag, DiaryDateTag } from '../models/index.js'; -import { devLog } from '../utils/logger.js'; export const getTags = async (req, res) => { try { const tags = await DiaryTag.findAll(); @@ -13,9 +12,12 @@ export const getTags = async (req, res) => { export const createTag = async (req, res) => { try { const { name } = req.body; - devLog(name); - const newTag = await DiaryTag.findOrCreate({ where: { name }, defaults: { name } }); - res.status(201).json(newTag); + if (!name) { + return res.status(400).json({ error: 'Der Name des Tags ist erforderlich.' }); + } + + const [tag, created] = await DiaryTag.findOrCreate({ where: { name }, defaults: { name } }); + res.status(created ? 201 : 200).json(tag); } catch (error) { res.status(500).json({ error: 'Error creating tag' }); } @@ -24,9 +26,14 @@ export const createTag = async (req, res) => { export const deleteTag = async (req, res) => { try { const { tagId } = req.params; - const { authcode: userToken } = req.headers; - const { clubId } = req.params; - await diaryService.removeTagFromDiaryDate(userToken, clubId, tagId); + + await DiaryDateTag.destroy({ where: { tagId } }); + const deleted = await DiaryTag.destroy({ where: { id: tagId } }); + + if (!deleted) { + return res.status(404).json({ error: 'Tag nicht gefunden' }); + } + res.status(200).json({ message: 'Tag deleted' }); } catch (error) { console.error('[deleteTag] - Error:', error); diff --git a/backend/controllers/matchController.js b/backend/controllers/matchController.js index 52f24e1..0547674 100644 --- a/backend/controllers/matchController.js +++ b/backend/controllers/matchController.js @@ -58,3 +58,90 @@ export const getMatchesForLeague = async (req, res) => { return res.status(500).json({ error: 'Failed to retrieve matches' }); } }; + +export const getLeagueTable = async (req, res) => { + try { + const { authcode: userToken } = req.headers; + const { clubId, leagueId } = req.params; + const table = await MatchService.getLeagueTable(userToken, clubId, leagueId); + return res.status(200).json(table); + } catch (error) { + console.error('Error retrieving league table:', error); + return res.status(500).json({ error: 'Failed to retrieve league table' }); + } +}; + +export const fetchLeagueTableFromMyTischtennis = async (req, res) => { + try { + const { authcode: userToken } = req.headers; + const { clubId, leagueId } = req.params; + const { userid: userIdOrEmail } = req.headers; + + // Convert email to userId if needed + let userId = userIdOrEmail; + if (isNaN(userIdOrEmail)) { + const User = (await import('../models/User.js')).default; + const user = await User.findOne({ where: { email: userIdOrEmail } }); + if (!user) { + return res.status(404).json({ error: 'User not found' }); + } + userId = user.id; + } + + const autoFetchService = (await import('../services/autoFetchMatchResultsService.js')).default; + await autoFetchService.fetchAndUpdateLeagueTable(userId, leagueId); + + // Return updated table data + const table = await MatchService.getLeagueTable(userToken, clubId, leagueId); + return res.status(200).json({ + message: 'League table updated from MyTischtennis', + data: table + }); + } catch (error) { + console.error('Error fetching league table from MyTischtennis:', error); + return res.status(500).json({ error: 'Failed to fetch league table from MyTischtennis' }); + } +}; + +export const updateMatchPlayers = async (req, res) => { + try { + const { authcode: userToken } = req.headers; + const { matchId } = req.params; + const { playersReady, playersPlanned, playersPlayed } = req.body; + + const result = await MatchService.updateMatchPlayers( + userToken, + matchId, + playersReady, + playersPlanned, + playersPlayed + ); + + return res.status(200).json({ + message: 'Match players updated successfully', + data: result + }); + } catch (error) { + console.error('Error updating match players:', error); + return res.status(error.statusCode || 500).json({ + error: error.message || 'Failed to update match players' + }); + } +}; + +export const getPlayerMatchStats = async (req, res) => { + try { + const { authcode: userToken } = req.headers; + const { clubId, leagueId } = req.params; + const { seasonid: seasonId } = req.query; + + const stats = await MatchService.getPlayerMatchStats(userToken, clubId, leagueId, seasonId); + + return res.status(200).json(stats); + } catch (error) { + console.error('Error retrieving player match stats:', error); + return res.status(error.statusCode || 500).json({ + error: error.message || 'Failed to retrieve player match stats' + }); + } +}; diff --git a/backend/controllers/memberActivityController.js b/backend/controllers/memberActivityController.js new file mode 100644 index 0000000..d91791d --- /dev/null +++ b/backend/controllers/memberActivityController.js @@ -0,0 +1,232 @@ +import { checkAccess } from '../utils/userUtils.js'; +import DiaryMemberActivity from '../models/DiaryMemberActivity.js'; +import DiaryDateActivity from '../models/DiaryDateActivity.js'; +import DiaryDates from '../models/DiaryDates.js'; +import Participant from '../models/Participant.js'; +import PredefinedActivity from '../models/PredefinedActivity.js'; +import GroupActivity from '../models/GroupActivity.js'; +import { Op } from 'sequelize'; + +export const getMemberActivities = async (req, res) => { + try { + const { authcode: userToken } = req.headers; + const { clubId, memberId } = req.params; + const { period } = req.query; // 'month', '3months', '6months', 'year', 'all' + + await checkAccess(userToken, clubId); + + // Calculate date range based on period + const now = new Date(); + let startDate = null; + + switch (period) { + case 'month': + startDate = new Date(now.getFullYear(), now.getMonth() - 1, now.getDate()); + break; + case '3months': + startDate = new Date(now.getFullYear(), now.getMonth() - 3, now.getDate()); + break; + case '6months': + startDate = new Date(now.getFullYear(), now.getMonth() - 6, now.getDate()); + break; + case 'year': + startDate = new Date(now.getFullYear() - 1, now.getMonth(), now.getDate()); + break; + case 'all': + default: + startDate = null; + break; + } + + // Get participant ID for this member + const participants = await Participant.findAll({ + where: { memberId: memberId } + }); + + if (participants.length === 0) { + return res.status(200).json([]); + } + + const participantIds = participants.map(p => p.id); + + // Get all diary member activities for this member + const whereClause = { + participantId: participantIds + }; + + const memberActivities = await DiaryMemberActivity.findAll({ + where: whereClause, + include: [ + { + model: Participant, + as: 'participant', + attributes: ['id', 'groupId', 'diaryDateId'] + }, + { + model: DiaryDateActivity, + as: 'activity', + include: [ + { + model: DiaryDates, + as: 'diaryDate', + where: startDate ? { + date: { + [Op.gte]: startDate + } + } : {} + }, + { + model: PredefinedActivity, + as: 'predefinedActivity' + }, + { + model: GroupActivity, + as: 'groupActivities', + required: false + } + ] + } + ], + order: [[{ model: DiaryDateActivity, as: 'activity' }, { model: DiaryDates, as: 'diaryDate' }, 'date', 'DESC']] + }); + + // Group activities by name and count occurrences, considering group assignment + const activityMap = new Map(); + + for (const ma of memberActivities) { + if (!ma.activity || !ma.activity.predefinedActivity || !ma.participant) { + continue; + } + + // Check group assignment + const participantGroupId = ma.participant.groupId; + const activityGroupIds = ma.activity.groupActivities?.map(ga => ga.groupId) || []; + + // Filter: Only count if: + // 1. Activity has no group assignment (empty activityGroupIds) - activity is for all groups OR + // 2. Participant's group matches one of the activity's groups + const shouldCount = activityGroupIds.length === 0 || + (participantGroupId !== null && activityGroupIds.includes(participantGroupId)); + + if (!shouldCount) { + continue; + } + + const activity = ma.activity.predefinedActivity; + const activityName = activity.name; + const date = ma.activity.diaryDate?.date; + + if (!activityMap.has(activityName)) { + activityMap.set(activityName, { + name: activityName, + count: 0, + dates: [] + }); + } + + const activityData = activityMap.get(activityName); + activityData.count++; + if (date) { + activityData.dates.push(date); + } + } + + // Convert map to array and sort by count + const activities = Array.from(activityMap.values()) + .sort((a, b) => b.count - a.count); + + return res.status(200).json(activities); + + } catch (error) { + console.error('Error fetching member activities:', error); + return res.status(500).json({ error: 'Failed to fetch member activities' }); + } +}; + +export const getMemberLastParticipations = async (req, res) => { + try { + const { authcode: userToken } = req.headers; + const { clubId, memberId } = req.params; + const { limit = 3 } = req.query; + + await checkAccess(userToken, clubId); + + // Get participant ID for this member + const participants = await Participant.findAll({ + where: { memberId: memberId } + }); + + if (participants.length === 0) { + return res.status(200).json([]); + } + + const participantIds = participants.map(p => p.id); + + // Get last participations for this member + const memberActivities = await DiaryMemberActivity.findAll({ + where: { + participantId: participantIds + }, + include: [ + { + model: Participant, + as: 'participant', + attributes: ['id', 'groupId', 'diaryDateId'] + }, + { + model: DiaryDateActivity, + as: 'activity', + include: [ + { + model: DiaryDates, + as: 'diaryDate' + }, + { + model: PredefinedActivity, + as: 'predefinedActivity' + }, + { + model: GroupActivity, + as: 'groupActivities', + required: false + } + ] + } + ], + order: [[{ model: DiaryDateActivity, as: 'activity' }, { model: DiaryDates, as: 'diaryDate' }, 'date', 'DESC']], + limit: parseInt(limit) * 10 // Get more to filter by group + }); + + // Format the results, considering group assignment + const participations = memberActivities + .filter(ma => { + if (!ma.activity || !ma.activity.predefinedActivity || !ma.activity.diaryDate || !ma.participant) { + return false; + } + + // Check group assignment + const participantGroupId = ma.participant.groupId; + const activityGroupIds = ma.activity.groupActivities?.map(ga => ga.groupId) || []; + + // Filter: Only count if: + // 1. Activity has no group assignment (empty activityGroupIds) - activity is for all groups OR + // 2. Participant's group matches one of the activity's groups + return activityGroupIds.length === 0 || + (participantGroupId !== null && activityGroupIds.includes(participantGroupId)); + }) + .slice(0, parseInt(limit)) // Limit after filtering + .map(ma => ({ + id: ma.id, + activityName: ma.activity.predefinedActivity.name, + date: ma.activity.diaryDate.date, + diaryDateId: ma.activity.diaryDate.id + })); + + return res.status(200).json(participations); + + } catch (error) { + console.error('Error fetching member last participations:', error); + return res.status(500).json({ error: 'Failed to fetch member last participations' }); + } +}; + diff --git a/backend/controllers/memberController.js b/backend/controllers/memberController.js index d22f085..36ddbc1 100644 --- a/backend/controllers/memberController.js +++ b/backend/controllers/memberController.js @@ -1,13 +1,12 @@ import MemberService from "../services/memberService.js"; +import MemberTransferService from "../services/memberTransferService.js"; import { devLog } from '../utils/logger.js'; const getClubMembers = async(req, res) => { try { const { authcode: userToken } = req.headers; - const { id: clubId, showAll } = req.params; - if (showAll === null) { - showAll = false; - } + const { id: clubId } = req.params; + const showAll = req.params.showAll ?? 'false'; res.status(200).json(await MemberService.getClubMembers(userToken, clubId, showAll)); } catch(error) { res.status(500).json({ error: 'systemerror' }); @@ -27,16 +26,16 @@ const getWaitingApprovals = async(req, res) => { const setClubMembers = async (req, res) => { try { - const { id: memberId, firstname: firstName, lastname: lastName, street, city, birthdate, phone, email, active, - testMembership, picsInInternetAllowed, gender, ttr, qttr } = req.body; + const { id: memberId, firstname: firstName, lastname: lastName, street, city, postalCode, birthdate, phone, email, active, + testMembership, picsInInternetAllowed, gender, ttr, qttr, memberFormHandedOver, contacts } = req.body; const { id: clubId } = req.params; const { authcode: userToken } = req.headers; - const addResult = await MemberService.setClubMember(userToken, clubId, memberId, firstName, lastName, street, city, birthdate, - phone, email, active, testMembership, picsInInternetAllowed, gender, ttr, qttr); + const addResult = await MemberService.setClubMember(userToken, clubId, memberId, firstName, lastName, street, city, postalCode, birthdate, + phone, email, active, testMembership, picsInInternetAllowed, gender, ttr, qttr, memberFormHandedOver, contacts); res.status(addResult.status || 500).json(addResult.response); } catch (error) { console.error('[setClubMembers] - Error:', error); - res.status(500).json({ error: 'Failed to upload image' }); + res.status(500).json({ error: 'Failed to save member' }); } } @@ -44,8 +43,12 @@ const uploadMemberImage = async (req, res) => { try { const { clubId, memberId } = req.params; const { authcode: userToken } = req.headers; - const result = await MemberService.uploadMemberImage(userToken, clubId, memberId, req.file.buffer); - res.status(result.status).json(result.message ? { message: result.message } : { error: result.error }); + const makePrimary = + req.body?.makePrimary === true || + req.body?.makePrimary === 'true' || + req.query?.makePrimary === 'true'; + const result = await MemberService.uploadMemberImage(userToken, clubId, memberId, req.file.buffer, { makePrimary }); + res.status(result.status).json(result.response ?? { success: false, error: 'Unknown upload result' }); } catch (error) { console.error('[uploadMemberImage] - Error:', error); res.status(500).json({ error: 'Failed to upload image' }); @@ -54,9 +57,11 @@ const uploadMemberImage = async (req, res) => { const getMemberImage = async (req, res) => { try { - const { clubId, memberId } = req.params; + const { clubId, memberId, imageId } = req.params; const { authcode: userToken } = req.headers; - const result = await MemberService.getMemberImage(userToken, clubId, memberId); + // Support "latest" as imageId to get the latest image + const actualImageId = imageId === 'latest' ? null : (imageId || null); + const result = await MemberService.getMemberImage(userToken, clubId, memberId, actualImageId); if (result.status === 200) { res.sendFile(result.imagePath); } else { @@ -80,4 +85,162 @@ const updateRatingsFromMyTischtennis = async (req, res) => { } }; -export { getClubMembers, getWaitingApprovals, setClubMembers, uploadMemberImage, getMemberImage, updateRatingsFromMyTischtennis }; \ No newline at end of file +const rotateMemberImage = async (req, res) => { + try { + const { clubId, memberId, imageId } = req.params; + const { direction } = req.body; + const { authcode: userToken } = req.headers; + + if (!direction || !['left', 'right'].includes(direction)) { + return res.status(400).json({ + success: false, + error: 'Ungültige Drehrichtung. Verwenden Sie "left" oder "right".' + }); + } + + const result = await MemberService.rotateMemberImage(userToken, clubId, memberId, imageId, direction); + res.status(result.status).json(result.response); + } catch (error) { + console.error('[rotateMemberImage] - Error:', error); + res.status(500).json({ success: false, error: 'Failed to rotate image' }); + } +}; + +const deleteMemberImage = async (req, res) => { + try { + const { clubId, memberId, imageId } = req.params; + const { authcode: userToken } = req.headers; + const result = await MemberService.deleteMemberImage(userToken, clubId, memberId, imageId); + res.status(result.status).json(result.response); + } catch (error) { + console.error('[deleteMemberImage] - Error:', error); + res.status(500).json({ success: false, error: 'Failed to delete image' }); + } +}; + +const generateMemberGallery = async (req, res) => { + try { + const { clubId } = req.params; + const { authcode: userToken } = req.headers; + const size = parseInt(req.query.size) || 200; // Default: 200x200 + const format = req.query.format || 'image'; // 'image' or 'json' + const result = await MemberService.generateMemberGallery(userToken, clubId, size); + if (result.status === 200) { + if (format === 'json') { + // Return member information for interactive gallery + return res.status(200).json({ + members: result.galleryEntries.map(entry => ({ + memberId: entry.memberId, + firstName: entry.firstName, + lastName: entry.lastName, + fullName: entry.fullName + })) + }); + } + res.setHeader('Content-Type', 'image/png'); + res.setHeader('Cache-Control', 'no-store'); + return res.status(200).send(result.buffer); + } + return res.status(result.status).json({ error: result.error || 'Galerie konnte nicht erstellt werden' }); + } catch (error) { + console.error('[generateMemberGallery] - Error:', error); + res.status(500).json({ error: 'Failed to generate member gallery' }); + } +}; + +const setPrimaryMemberImage = async (req, res) => { + try { + const { clubId, memberId, imageId } = req.params; + const { authcode: userToken } = req.headers; + const result = await MemberService.setPrimaryMemberImage(userToken, clubId, memberId, imageId); + res.status(result.status).json(result.response); + } catch (error) { + console.error('[setPrimaryMemberImage] - Error:', error); + res.status(500).json({ success: false, error: 'Failed to update primary image' }); + } +}; + +const quickUpdateTestMembership = async (req, res) => { + try { + const { clubId, memberId } = req.params; + const { authcode: userToken } = req.headers; + const result = await MemberService.quickUpdateTestMembership(userToken, clubId, memberId); + res.status(result.status).json(result.response); + } catch (error) { + console.error('[quickUpdateTestMembership] - Error:', error); + res.status(500).json({ error: 'Failed to update test membership' }); + } +}; + +const quickUpdateMemberFormHandedOver = async (req, res) => { + try { + const { clubId, memberId } = req.params; + const { authcode: userToken } = req.headers; + const result = await MemberService.quickUpdateMemberFormHandedOver(userToken, clubId, memberId); + res.status(result.status).json(result.response); + } catch (error) { + console.error('[quickUpdateMemberFormHandedOver] - Error:', error); + res.status(500).json({ error: 'Failed to update member form status' }); + } +}; + +const quickDeactivateMember = async (req, res) => { + try { + const { clubId, memberId } = req.params; + const { authcode: userToken } = req.headers; + const result = await MemberService.quickDeactivateMember(userToken, clubId, memberId); + res.status(result.status).json(result.response); + } catch (error) { + console.error('[quickDeactivateMember] - Error:', error); + res.status(500).json({ error: 'Failed to deactivate member' }); + } +}; + +const transferMembers = async (req, res) => { + try { + const { id: clubId } = req.params; + const { authcode: userToken } = req.headers; + const config = req.body; + + // Validierung + if (!config.transferEndpoint) { + return res.status(400).json({ + success: false, + error: 'Übertragungs-Endpoint ist erforderlich' + }); + } + + if (!config.transferTemplate) { + return res.status(400).json({ + success: false, + error: 'Übertragungs-Template ist erforderlich' + }); + } + + const result = await MemberTransferService.transferMembers(userToken, clubId, config); + res.status(result.status).json(result.response); + } catch (error) { + console.error('[transferMembers] - Error:', error); + res.status(500).json({ + success: false, + error: 'Fehler bei der Übertragung: ' + error.message + }); + } +}; + +export { + getClubMembers, + getWaitingApprovals, + setClubMembers, + uploadMemberImage, + getMemberImage, + updateRatingsFromMyTischtennis, + rotateMemberImage, + transferMembers, + quickUpdateTestMembership, + quickUpdateMemberFormHandedOver, + quickDeactivateMember, + deleteMemberImage, + setPrimaryMemberImage, + generateMemberGallery +}; \ No newline at end of file diff --git a/backend/controllers/memberNoteController.js b/backend/controllers/memberNoteController.js index 7a8f026..78c3467 100644 --- a/backend/controllers/memberNoteController.js +++ b/backend/controllers/memberNoteController.js @@ -1,4 +1,5 @@ import MemberNoteService from "../services/memberNoteService.js"; +import MemberNote from '../models/MemberNote.js'; import { devLog } from '../utils/logger.js'; const getMemberNotes = async (req, res) => { @@ -21,6 +22,7 @@ const addMemberNote = async (req, res) => { const notes = await MemberNoteService.getNotesForMember(userToken, clubId, memberId); res.status(201).json(notes); } catch (error) { + console.error('[addMemberNote] - Error:', error); res.status(500).json({ error: 'systemerror' }); } }; @@ -30,11 +32,16 @@ const deleteMemberNote = async (req, res) => { const { authcode: userToken } = req.headers; const { noteId } = req.params; const { clubId } = req.body; - const memberId = await MemberNoteService.getMemberIdForNote(noteId); // Member ID ermitteln + const note = await MemberNote.findByPk(noteId); + if (!note) { + return res.status(404).json({ error: 'notfound' }); + } + const memberId = note.memberId; await MemberNoteService.deleteNoteForMember(userToken, clubId, noteId); const notes = await MemberNoteService.getNotesForMember(userToken, clubId, memberId); res.status(200).json(notes); } catch (error) { + console.error('[deleteMemberNote] - Error:', error); res.status(500).json({ error: 'systemerror' }); } }; diff --git a/backend/controllers/memberTransferConfigController.js b/backend/controllers/memberTransferConfigController.js new file mode 100644 index 0000000..3a25a72 --- /dev/null +++ b/backend/controllers/memberTransferConfigController.js @@ -0,0 +1,51 @@ +import MemberTransferConfigService from '../services/memberTransferConfigService.js'; + +export const getConfig = async (req, res) => { + try { + const { id: clubId } = req.params; + const { authcode: userToken } = req.headers; + + const result = await MemberTransferConfigService.getConfig(userToken, clubId); + res.status(result.status).json(result.response); + } catch (error) { + console.error('[getConfig] Error:', error); + res.status(500).json({ + success: false, + error: 'Fehler beim Laden der Konfiguration' + }); + } +}; + +export const saveConfig = async (req, res) => { + try { + const { id: clubId } = req.params; + const { authcode: userToken } = req.headers; + const configData = req.body; + + const result = await MemberTransferConfigService.saveConfig(userToken, clubId, configData); + res.status(result.status).json(result.response); + } catch (error) { + console.error('[saveConfig] Error:', error); + res.status(500).json({ + success: false, + error: 'Fehler beim Speichern der Konfiguration' + }); + } +}; + +export const deleteConfig = async (req, res) => { + try { + const { id: clubId } = req.params; + const { authcode: userToken } = req.headers; + + const result = await MemberTransferConfigService.deleteConfig(userToken, clubId); + res.status(result.status).json(result.response); + } catch (error) { + console.error('[deleteConfig] Error:', error); + res.status(500).json({ + success: false, + error: 'Fehler beim Löschen der Konfiguration' + }); + } +}; + diff --git a/backend/controllers/myTischtennisController.js b/backend/controllers/myTischtennisController.js index 9c8d92c..7628aed 100644 --- a/backend/controllers/myTischtennisController.js +++ b/backend/controllers/myTischtennisController.js @@ -42,15 +42,15 @@ class MyTischtennisController { async upsertAccount(req, res, next) { try { const userId = req.user.id; - const { email, password, savePassword, userPassword } = req.body; + const { email, password, savePassword, autoUpdateRatings, userPassword } = req.body; if (!email) { - throw new HttpError(400, 'E-Mail-Adresse erforderlich'); + throw new HttpError('E-Mail-Adresse erforderlich', 400); } // Wenn ein Passwort gesetzt wird, muss das App-Passwort angegeben werden if (password && !userPassword) { - throw new HttpError(400, 'App-Passwort erforderlich zum Setzen des myTischtennis-Passworts'); + throw new HttpError('App-Passwort erforderlich zum Setzen des myTischtennis-Passworts', 400); } const account = await myTischtennisService.upsertAccount( @@ -58,6 +58,7 @@ class MyTischtennisController { email, password, savePassword || false, + autoUpdateRatings || false, userPassword ); @@ -80,7 +81,7 @@ class MyTischtennisController { const deleted = await myTischtennisService.deleteAccount(userId); if (!deleted) { - throw new HttpError(404, 'Kein myTischtennis-Account gefunden'); + throw new HttpError('Kein myTischtennis-Account gefunden', 404); } res.status(200).json({ message: 'myTischtennis-Account gelöscht' }); @@ -127,6 +128,77 @@ class MyTischtennisController { next(error); } } + + /** + * GET /api/mytischtennis/update-history + * Get update ratings history + */ + async getUpdateHistory(req, res, next) { + try { + const userId = req.user.id; + const history = await myTischtennisService.getUpdateHistory(userId); + res.status(200).json({ history }); + } catch (error) { + next(error); + } + } + + /** + * Get fetch logs for current user + */ + async getFetchLogs(req, res, next) { + try { + const { userid: userIdOrEmail } = req.headers; + + // Convert email to userId if needed + let userId = userIdOrEmail; + if (isNaN(userIdOrEmail)) { + const User = (await import('../models/User.js')).default; + const user = await User.findOne({ where: { email: userIdOrEmail } }); + if (!user) { + return res.status(404).json({ error: 'User not found' }); + } + userId = user.id; + } + + const fetchLogService = (await import('../services/myTischtennisFetchLogService.js')).default; + const logs = await fetchLogService.getFetchLogs(userId, { + limit: req.query.limit ? parseInt(req.query.limit) : 50, + fetchType: req.query.type + }); + + res.status(200).json({ logs }); + } catch (error) { + next(error); + } + } + + /** + * Get latest successful fetches for each type + */ + async getLatestFetches(req, res, next) { + try { + const { userid: userIdOrEmail } = req.headers; + + // Convert email to userId if needed + let userId = userIdOrEmail; + if (isNaN(userIdOrEmail)) { + const User = (await import('../models/User.js')).default; + const user = await User.findOne({ where: { email: userIdOrEmail } }); + if (!user) { + return res.status(404).json({ error: 'User not found' }); + } + userId = user.id; + } + + const fetchLogService = (await import('../services/myTischtennisFetchLogService.js')).default; + const latestFetches = await fetchLogService.getLatestSuccessfulFetches(userId); + + res.status(200).json({ latestFetches }); + } catch (error) { + next(error); + } + } } export default new MyTischtennisController(); diff --git a/backend/controllers/myTischtennisUrlController.js b/backend/controllers/myTischtennisUrlController.js new file mode 100644 index 0000000..72df2b1 --- /dev/null +++ b/backend/controllers/myTischtennisUrlController.js @@ -0,0 +1,601 @@ +import myTischtennisUrlParserService from '../services/myTischtennisUrlParserService.js'; +import myTischtennisService from '../services/myTischtennisService.js'; +import MemberService from '../services/memberService.js'; +import autoFetchMatchResultsService from '../services/autoFetchMatchResultsService.js'; +import apiLogService from '../services/apiLogService.js'; +import ClubTeam from '../models/ClubTeam.js'; +import League from '../models/League.js'; +import Season from '../models/Season.js'; +import User from '../models/User.js'; +import HttpError from '../exceptions/HttpError.js'; +import { devLog } from '../utils/logger.js'; + +class MyTischtennisUrlController { + /** + * Parse myTischtennis URL and return configuration data + * POST /api/mytischtennis/parse-url + * Body: { url: string } + */ + async parseUrl(req, res, next) { + try { + const { url } = req.body; + + if (!url) { + throw new HttpError('URL is required', 400); + } + + // Validate URL + if (!myTischtennisUrlParserService.isValidTeamUrl(url)) { + throw new HttpError('Invalid myTischtennis URL format', 400); + } + + // Parse URL + const parsedData = myTischtennisUrlParserService.parseUrl(url); + + // Try to fetch additional data if user is authenticated + const userIdOrEmail = req.headers.userid; + let completeData = parsedData; + + if (userIdOrEmail) { + // Get actual user ID + let userId = userIdOrEmail; + if (isNaN(userIdOrEmail)) { + const user = await User.findOne({ where: { email: userIdOrEmail } }); + if (user) userId = user.id; + } + + try { + const account = await myTischtennisService.getAccount(userId); + + if (account && account.accessToken) { + completeData = await myTischtennisUrlParserService.fetchTeamData( + parsedData, + account.cookie, + account.accessToken + ); + } + } catch (error) { + // Continue with parsed data only + } + } + + res.json({ + success: true, + data: completeData + }); + } catch (error) { + next(error); + } + } + + /** + * Configure team from myTischtennis URL + * POST /api/mytischtennis/configure-team + * Body: { url: string, clubTeamId: number, createLeague?: boolean, createSeason?: boolean } + */ + async configureTeam(req, res, next) { + try { + const { url, clubTeamId, createLeague, createSeason } = req.body; + const userIdOrEmail = req.headers.userid; + + if (!url || !clubTeamId) { + throw new HttpError('URL and clubTeamId are required', 400); + } + + // Get actual user ID + let userId = userIdOrEmail; + if (isNaN(userIdOrEmail)) { + const user = await User.findOne({ where: { email: userIdOrEmail } }); + if (!user) { + throw new HttpError('User not found', 404); + } + userId = user.id; + } + + // Parse URL + const parsedData = myTischtennisUrlParserService.parseUrl(url); + + // Try to fetch additional data + let completeData = parsedData; + const account = await myTischtennisService.getAccount(userId); + + if (account && account.accessToken) { + try { + completeData = await myTischtennisUrlParserService.fetchTeamData( + parsedData, + account.cookie, + account.accessToken + ); + } catch (error) { + } + } + + // Find or create season + let season = await Season.findOne({ + where: { season: completeData.season } + }); + + if (!season && createSeason) { + season = await Season.create({ + season: completeData.season + }); + } + + if (!season) { + throw new HttpError(`Season ${completeData.season} not found. Set createSeason=true to create it.`, 404); + } + + // Find or create league + const team = await ClubTeam.findByPk(clubTeamId); + if (!team) { + throw new HttpError('Club team not found', 404); + } + + let league; + + // First, try to find existing league by name and season + const leagueName = completeData.leagueName || completeData.groupname; + league = await League.findOne({ + where: { + name: leagueName, + seasonId: season.id, + clubId: team.clubId + } + }); + + if (league) { + devLog(`Found existing league: ${league.name} (ID: ${league.id})`); + // Update myTischtennis fields + await league.update({ + myTischtennisGroupId: completeData.groupId, + association: completeData.association, + groupname: completeData.groupname + }); + } else if (team.leagueId) { + // Team has a league assigned, update it + league = await League.findByPk(team.leagueId); + + if (league) { + devLog(`Updating team's existing league: ${league.name} (ID: ${league.id})`); + await league.update({ + name: leagueName, + myTischtennisGroupId: completeData.groupId, + association: completeData.association, + groupname: completeData.groupname + }); + } + } else if (createLeague) { + // Create new league + devLog(`Creating new league: ${leagueName}`); + league = await League.create({ + name: leagueName, + seasonId: season.id, + clubId: team.clubId, + myTischtennisGroupId: completeData.groupId, + association: completeData.association, + groupname: completeData.groupname + }); + } else { + throw new HttpError('League not found and team has no league assigned. Set createLeague=true to create one.', 400); + } + + // Update team + await team.update({ + myTischtennisTeamId: completeData.teamId, + leagueId: league.id, + seasonId: season.id + }); + + res.json({ + success: true, + message: 'Team configured successfully', + data: { + team: { + id: team.id, + name: team.name, + myTischtennisTeamId: completeData.teamId + }, + league: { + id: league.id, + name: league.name, + myTischtennisGroupId: completeData.groupId, + association: completeData.association, + groupname: completeData.groupname + }, + season: { + id: season.id, + name: season.season + }, + parsedData: completeData + } + }); + } catch (error) { + next(error); + } + } + + /** + * Manually fetch team data from myTischtennis + * POST /api/mytischtennis/fetch-team-data + * Body: { clubTeamId: number } + */ + async fetchTeamData(req, res, next) { + // Define outside of try/catch so catch has access + let account = null; + let team = null; + let myTischtennisUrl = null; + let requestStartTime = null; + try { + const { clubTeamId } = req.body; + const userIdOrEmail = req.headers.userid; + + if (!clubTeamId) { + throw new HttpError('clubTeamId is required', 400); + } + + if (!userIdOrEmail) { + throw new HttpError('User-ID fehlt. Bitte melden Sie sich an.', 401); + } + + // Get actual user ID (userid header might be email address) + let userId = userIdOrEmail; + if (isNaN(userIdOrEmail)) { + // It's an email, find the user + const user = await User.findOne({ where: { email: userIdOrEmail } }); + if (!user) { + throw new HttpError('User not found', 404); + } + userId = user.id; + } + + // Get myTischtennis session (similar to memberService.updateRatingsFromMyTischtennis) + let session; + + try { + session = await myTischtennisService.getSession(userId); + } catch (sessionError) { + // Versuche automatischen Login mit gespeicherten Credentials + try { + // Check if account exists and has password + const accountCheck = await myTischtennisService.getAccount(userId); + if (!accountCheck) { + throw new Error('MyTischtennis-Account nicht gefunden'); + } + + if (!accountCheck.encryptedPassword) { + throw new Error('Kein Passwort gespeichert. Bitte melden Sie sich in den MyTischtennis-Einstellungen an und speichern Sie Ihr Passwort.'); + } + + await myTischtennisService.verifyLogin(userId); + session = await myTischtennisService.getSession(userId); + } catch (loginError) { + const errorMessage = loginError.message || 'Automatischer Login fehlgeschlagen'; + throw new HttpError(`MyTischtennis-Session abgelaufen und automatischer Login fehlgeschlagen: ${errorMessage}. Bitte melden Sie sich in den MyTischtennis-Einstellungen an.`, 401); + } + } + + // Get account data (for clubId, etc.) + account = await myTischtennisService.getAccount(userId); + + if (!account) { + throw new HttpError('MyTischtennis-Account nicht verknüpft. Bitte verknüpfen Sie Ihren Account in den MyTischtennis-Einstellungen.', 404); + } + + + // Get team with league and season + team = await ClubTeam.findByPk(clubTeamId, { + include: [ + { + model: League, + as: 'league', + include: [ + { + model: Season, + as: 'season' + } + ] + } + ] + }); + + if (!team) { + throw new HttpError(`Team mit ID ${clubTeamId} nicht gefunden`, 404); + } + + // Verbesserte Validierung mit detaillierten Fehlermeldungen + if (!team.myTischtennisTeamId) { + throw new HttpError(`Team "${team.name}" (interne ID: ${team.id}) ist nicht für myTischtennis konfiguriert: myTischtennisTeamId fehlt. Bitte konfigurieren Sie das Team zuerst über die MyTischtennis-URL.`, 400); + } + + if (!team.league) { + throw new HttpError('Team ist keiner Liga zugeordnet. Bitte ordnen Sie das Team einer Liga zu.', 400); + } + + if (!team.league.myTischtennisGroupId) { + throw new HttpError('Liga ist nicht für myTischtennis konfiguriert: myTischtennisGroupId fehlt. Bitte konfigurieren Sie die Liga zuerst über die MyTischtennis-URL.', 400); + } + + // Validate season before proceeding + if (!team.league.season || !team.league.season.season) { + throw new HttpError('Liga ist keiner Saison zugeordnet. Bitte ordnen Sie die Liga einer Saison zu.', 400); + } + + // Build the URL that will be used - do this early so we can log it even if errors occur + const seasonFull = team.league.season.season; + const seasonParts = seasonFull.split('/'); + const seasonShort = seasonParts.length === 2 + ? `${seasonParts[0].slice(-2)}/${seasonParts[1].slice(-2)}` + : seasonFull; + const seasonStr = seasonShort.replace('/', '--'); + const teamnameEncoded = encodeURIComponent(team.name.replace(/\s/g, '_')); + myTischtennisUrl = `https://www.mytischtennis.de/click-tt/${team.league.association}/${seasonStr}/ligen/${team.league.groupname}/gruppe/${team.league.myTischtennisGroupId}/mannschaft/${team.myTischtennisTeamId}/${teamnameEncoded}/spielerbilanzen/gesamt`; + + // Log the request to myTischtennis BEFORE making the call + // This ensures we always see what WILL BE sent, even if the call fails + requestStartTime = Date.now(); + try { + await apiLogService.logRequest({ + userId: account.userId, + method: 'GET', + path: myTischtennisUrl.replace('https://www.mytischtennis.de', ''), + statusCode: null, + requestBody: JSON.stringify({ + url: myTischtennisUrl, + myTischtennisTeamId: team.myTischtennisTeamId, + clubTeamId: team.id, + teamName: team.name, + leagueName: team.league.name, + association: team.league.association, + groupId: team.league.myTischtennisGroupId, + groupname: team.league.groupname, + season: seasonFull + }), + responseBody: null, + executionTime: null, + errorMessage: 'Request wird ausgeführt...', + logType: 'api_request', + schedulerJobType: 'mytischtennis_fetch' + }); + } catch (logError) { + // Silent fail - logging errors shouldn't break the request + } + + // Fetch data for this specific team + // Note: fetchTeamResults will also log and update with actual response + const result = await autoFetchMatchResultsService.fetchTeamResults( + { + userId: account.userId, + email: account.email, + cookie: session.cookie, + accessToken: session.accessToken, + expiresAt: session.expiresAt, + getPassword: () => null // Not needed for manual fetch + }, + team + ); + + // Also fetch and update league table data + let tableUpdateResult = null; + try { + await autoFetchMatchResultsService.fetchAndUpdateLeagueTable(account.userId, team.league.id); + tableUpdateResult = 'League table updated successfully'; + } catch (error) { + tableUpdateResult = 'League table update failed: ' + error.message; + // Don't fail the entire request if table update fails + } + + // Additionally update (Q)TTR ratings for the club + let ratingsUpdate = null; + try { + // Use already resolved userId instead of authcode to avoid header dependency + const ratingsResult = await MemberService.updateRatingsFromMyTischtennisByUserId(userId, team.clubId); + ratingsUpdate = ratingsResult?.response?.message || `Ratings update status: ${ratingsResult?.status}`; + } catch (ratingsErr) { + ratingsUpdate = 'Ratings update failed: ' + (ratingsErr.message || String(ratingsErr)); + } + + res.json({ + success: true, + message: `${result.fetchedCount} Datensätze abgerufen und verarbeitet`, + data: { + fetchedCount: result.fetchedCount, + teamName: team.name, + tableUpdate: tableUpdateResult, + ratingsUpdate + } + }); + } catch (error) { + + // Update log with error information if we got far enough to build the URL + if (myTischtennisUrl && account && team) { + const requestExecutionTime = requestStartTime ? (Date.now() - requestStartTime) : null; + try { + await apiLogService.logRequest({ + userId: account.userId, + method: 'GET', + path: myTischtennisUrl.replace('https://www.mytischtennis.de', ''), + statusCode: 0, + requestBody: JSON.stringify({ + url: myTischtennisUrl, + myTischtennisTeamId: team.myTischtennisTeamId, + clubTeamId: team.id, + teamName: team.name, + leagueName: team.league?.name, + association: team.league?.association, + groupname: team.league?.groupname, + groupId: team.league?.myTischtennisGroupId + }), + responseBody: null, + executionTime: requestExecutionTime, + errorMessage: error.message || String(error), + logType: 'api_request', + schedulerJobType: 'mytischtennis_fetch' + }); + } catch (logError) { + // Silent fail - logging errors shouldn't break the request + } + } + + // Normalize HTTP status code (guard against strings) + const rawCode = error && (error.statusCode != null ? error.statusCode : error.status); + const parsed = Number(rawCode); + const status = Number.isInteger(parsed) && parsed >= 100 && parsed <= 599 ? parsed : 500; + const debug = { + message: error.message || String(error), + name: error.name, + stack: (process.env.NODE_ENV === 'dev' || process.env.NODE_ENV === 'development') ? (error.stack || null) : undefined, + team: team ? { id: team.id, name: team.name } : null, + league: team && team.league ? { id: team.league.id, name: team.league.name, association: team.league.association, groupId: team.league.myTischtennisGroupId, groupname: team.league.groupname } : null, + url: typeof myTischtennisUrl !== 'undefined' ? myTischtennisUrl : null + }; + try { + if (!res.headersSent) { + // Spezieller Fall: myTischtennis-Reauth nötig → nicht 401 an FE senden, um App-Logout zu vermeiden + const isMyTischtennisAuthIssue = status === 401 && /MyTischtennis-Session abgelaufen|Automatischer Login fehlgeschlagen|Passwort gespeichert/i.test(debug.message || ''); + if (isMyTischtennisAuthIssue) { + return res.status(200).json({ success: false, error: debug.message, debug, needsMyTischtennisReauth: true }); + } + res.status(status).json({ success: false, error: debug.message, debug }); + } + } catch (writeErr) { + // Fallback, falls Headers schon gesendet wurden + // eslint-disable-next-line no-console + console.error('[fetchTeamData] Response write failed:', writeErr); + } + } + } + + /** + * Get myTischtennis URL for a team + * GET /api/mytischtennis/team-url/:teamId + */ + async getTeamUrl(req, res, next) { + try { + const { teamId } = req.params; + + const team = await ClubTeam.findByPk(teamId, { + include: [ + { + model: League, + as: 'league', + include: [ + { + model: Season, + as: 'season' + } + ] + } + ] + }); + + if (!team) { + throw new HttpError('Team not found', 404); + } + + if (!team.myTischtennisTeamId || !team.league || !team.league.myTischtennisGroupId) { + throw new HttpError('Team is not configured for myTischtennis', 400); + } + + const url = myTischtennisUrlParserService.buildUrl({ + association: team.league.association, + season: team.league.season?.season, + groupname: team.league.groupname, + groupId: team.league.myTischtennisGroupId, + teamId: team.myTischtennisTeamId, + teamname: team.name + }); + + res.json({ + success: true, + url + }); + } catch (error) { + next(error); + } + } + + /** + * Configure league from myTischtennis table URL + * POST /api/mytischtennis/configure-league + * Body: { url: string, createSeason?: boolean } + */ + async configureLeague(req, res, next) { + try { + const { url, createSeason } = req.body; + const userIdOrEmail = req.headers.userid; + + if (!url) { + throw new HttpError('URL is required', 400); + } + + // Parse URL + const parsedData = myTischtennisUrlParserService.parseUrl(url); + + if (parsedData.urlType !== 'table') { + throw new HttpError('URL must be a table URL (not a team URL)', 400); + } + + // Find or create season + let season = await Season.findOne({ + where: { season: parsedData.season } + }); + + if (!season && createSeason) { + season = await Season.create({ + season: parsedData.season, + startDate: new Date(), + endDate: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000) // 1 Jahr später + }); + } + + // Find or create league + let league = await League.findOne({ + where: { + myTischtennisGroupId: parsedData.groupId, + association: parsedData.association + } + }); + + if (!league) { + league = await League.create({ + name: parsedData.groupnameOriginal, // Verwende die originale URL-kodierte Version + myTischtennisGroupId: parsedData.groupId, + association: parsedData.association, + groupname: parsedData.groupnameOriginal, // Verwende die originale URL-kodierte Version + seasonId: season?.id || null + }); + } else { + // Update existing league - aber nur wenn es sich wirklich geändert hat + if (league.name !== parsedData.groupnameOriginal) { + league.name = parsedData.groupnameOriginal; + league.groupname = parsedData.groupnameOriginal; + } + league.seasonId = season?.id || league.seasonId; + await league.save(); + } + + res.json({ + success: true, + message: 'League configured successfully', + data: { + league: { + id: league.id, + name: league.name, + myTischtennisGroupId: league.myTischtennisGroupId, + association: league.association, + groupname: league.groupname + }, + season: season ? { + id: season.id, + name: season.season + } : null, + parsedData + } + }); + } catch (error) { + next(error); + } + } +} + +export default new MyTischtennisUrlController(); diff --git a/backend/controllers/participantController.js b/backend/controllers/participantController.js index fe5b83d..4787477 100644 --- a/backend/controllers/participantController.js +++ b/backend/controllers/participantController.js @@ -4,7 +4,10 @@ import { devLog } from '../utils/logger.js'; export const getParticipants = async (req, res) => { try { const { dateId } = req.params; - const participants = await Participant.findAll({ where: { diaryDateId: dateId } }); + const participants = await Participant.findAll({ + where: { diaryDateId: dateId }, + attributes: ['id', 'diaryDateId', 'memberId', 'groupId', 'notes', 'createdAt', 'updatedAt'] + }); res.status(200).json(participants); } catch (error) { devLog(error); @@ -12,6 +15,32 @@ export const getParticipants = async (req, res) => { } }; +export const updateParticipantGroup = async (req, res) => { + try { + const { dateId, memberId } = req.params; + const { groupId } = req.body; + + const participant = await Participant.findOne({ + where: { + diaryDateId: dateId, + memberId: memberId + } + }); + + if (!participant) { + return res.status(404).json({ error: 'Teilnehmer nicht gefunden' }); + } + + participant.groupId = groupId || null; + await participant.save(); + + res.status(200).json(participant); + } catch (error) { + devLog(error); + res.status(500).json({ error: 'Fehler beim Aktualisieren der Teilnehmer-Gruppenzuordnung' }); + } +}; + export const addParticipant = async (req, res) => { try { const { diaryDateId, memberId } = req.body; diff --git a/backend/controllers/permissionController.js b/backend/controllers/permissionController.js new file mode 100644 index 0000000..43306ea --- /dev/null +++ b/backend/controllers/permissionController.js @@ -0,0 +1,167 @@ +import permissionService from '../services/permissionService.js'; + +/** + * Get user's permissions for a club + */ +export const getUserPermissions = async (req, res) => { + try { + const { clubId } = req.params; + const userId = req.user.id; + + // Validierung: clubId muss eine gültige Zahl sein + const parsedClubId = parseInt(clubId, 10); + if (isNaN(parsedClubId) || parsedClubId <= 0) { + return res.status(400).json({ error: 'Ungültige Club-ID' }); + } + + const permissions = await permissionService.getUserClubPermissions(userId, parsedClubId); + + if (!permissions) { + return res.status(404).json({ error: 'Keine Berechtigungen gefunden' }); + } + + res.json(permissions); + } catch (error) { + console.error('Error getting user permissions:', error); + res.status(500).json({ error: 'Fehler beim Abrufen der Berechtigungen' }); + } +}; + +/** + * Get all club members with their permissions + */ +export const getClubMembersWithPermissions = async (req, res) => { + try { + const { clubId } = req.params; + const userId = req.user.id; + + const members = await permissionService.getClubMembersWithPermissions( + parseInt(clubId), + userId + ); + + res.json(members); + } catch (error) { + console.error('Error getting club members with permissions:', error); + if (error.message === 'Keine Berechtigung zum Anzeigen von Berechtigungen') { + return res.status(403).json({ error: error.message }); + } + res.status(500).json({ error: 'Fehler beim Abrufen der Mitglieder' }); + } +}; + +/** + * Update user role + */ +export const updateUserRole = async (req, res) => { + try { + const { clubId, userId: targetUserId } = req.params; + const { role } = req.body; + const updatingUserId = req.user.id; + + const result = await permissionService.setUserRole( + parseInt(targetUserId), + parseInt(clubId), + role, + updatingUserId + ); + + res.json(result); + } catch (error) { + console.error('Error updating user role:', error); + if (error.message && error.message.toLowerCase().includes('keine berechtigung')) { + return res.status(403).json({ error: error.message }); + } + res.status(400).json({ error: error.message }); + } +}; + +/** + * Update user custom permissions + */ +export const updateUserPermissions = async (req, res) => { + try { + const { clubId, userId: targetUserId } = req.params; + const { permissions } = req.body; + const updatingUserId = req.user.id; + + const result = await permissionService.setCustomPermissions( + parseInt(targetUserId), + parseInt(clubId), + permissions, + updatingUserId + ); + + res.json(result); + } catch (error) { + console.error('Error updating user permissions:', error); + if (error.message && error.message.toLowerCase().includes('keine berechtigung')) { + return res.status(403).json({ error: error.message }); + } + res.status(400).json({ error: error.message }); + } +}; + +/** + * Get available roles + */ +export const getAvailableRoles = async (req, res) => { + try { + const roles = permissionService.getAvailableRoles(); + res.json(roles); + } catch (error) { + console.error('Error getting available roles:', error); + res.status(500).json({ error: 'Fehler beim Abrufen der Rollen' }); + } +}; + +/** + * Get permission structure + */ +export const getPermissionStructure = async (req, res) => { + try { + const structure = permissionService.getPermissionStructure(); + res.json(structure); + } catch (error) { + console.error('Error getting permission structure:', error); + res.status(500).json({ error: 'Fehler beim Abrufen der Berechtigungsstruktur' }); + } +}; + +/** + * Update user status (activate/deactivate) + */ +export const updateUserStatus = async (req, res) => { + try { + const { clubId, userId: targetUserId } = req.params; + const { approved } = req.body; + const updatingUserId = req.user.id; + + const result = await permissionService.setUserStatus( + parseInt(targetUserId), + parseInt(clubId), + approved, + updatingUserId + ); + + res.json(result); + } catch (error) { + console.error('Error updating user status:', error); + if (error.message && error.message.toLowerCase().includes('keine berechtigung')) { + return res.status(403).json({ error: error.message }); + } + res.status(400).json({ error: error.message }); + } +}; + +export default { + getUserPermissions, + getClubMembersWithPermissions, + updateUserRole, + updateUserPermissions, + updateUserStatus, + getAvailableRoles, + getPermissionStructure +}; + + diff --git a/backend/controllers/teamDocumentController.js b/backend/controllers/teamDocumentController.js index 2ab238e..ed3a554 100644 --- a/backend/controllers/teamDocumentController.js +++ b/backend/controllers/teamDocumentController.js @@ -1,5 +1,6 @@ import multer from 'multer'; import path from 'path'; +import fs from 'fs'; import TeamDocumentService from '../services/teamDocumentService.js'; import PDFParserService from '../services/pdfParserService.js'; import { getUserByToken } from '../utils/userUtils.js'; @@ -8,6 +9,11 @@ import { devLog } from '../utils/logger.js'; // Multer-Konfiguration für Datei-Uploads const storage = multer.diskStorage({ destination: (req, file, cb) => { + try { + fs.mkdirSync('uploads/temp', { recursive: true }); + } catch (mkdirError) { + console.error('[multer] - Failed to ensure temp upload directory exists:', mkdirError); + } cb(null, 'uploads/temp/'); }, filename: (req, file, cb) => { @@ -23,15 +29,17 @@ const upload = multer({ }, fileFilter: (req, file, cb) => { // Erlaube nur PDF, DOC, DOCX, TXT, CSV Dateien - const allowedTypes = /pdf|doc|docx|txt|csv/; - const extname = allowedTypes.test(path.extname(file.originalname).toLowerCase()); - const mimetype = allowedTypes.test(file.mimetype); + const allowedExtensions = ['.pdf', '.doc', '.docx', '.txt', '.csv']; + const allowedMimePatterns = ['pdf', 'msword', 'wordprocessingml.document', 'text/plain', 'csv', 'excel']; - if (mimetype && extname) { + const extensionValid = allowedExtensions.includes(path.extname(file.originalname).toLowerCase()); + const mimetypeValid = allowedMimePatterns.some((pattern) => file.mimetype && file.mimetype.toLowerCase().includes(pattern)); + + if (extensionValid && mimetypeValid) { return cb(null, true); - } else { - cb(new Error('Nur PDF, DOC, DOCX, TXT und CSV Dateien sind erlaubt!')); } + + cb(new Error('Nur PDF, DOC, DOCX, TXT und CSV Dateien sind erlaubt!')); } }); diff --git a/backend/database.js b/backend/database.js index 8c31de0..19682fb 100644 --- a/backend/database.js +++ b/backend/database.js @@ -10,7 +10,8 @@ const sequelize = new Sequelize( host: development.host, dialect: development.dialect, define: development.define, - logging: false, // SQL-Logging deaktivieren + logging: development.logging ?? false, + storage: development.storage, } ); diff --git a/backend/middleware/authMiddleware.js b/backend/middleware/authMiddleware.js index 2e5d43c..fe962a5 100644 --- a/backend/middleware/authMiddleware.js +++ b/backend/middleware/authMiddleware.js @@ -6,6 +6,9 @@ export const authenticate = async (req, res, next) => { if (!token) { token = req.headers['authcode']; } + if (!token) { + token = req.query?.authcode || req.query?.token || null; + } if (!token) { return res.status(401).json({ error: 'Unauthorized: Token fehlt' }); } diff --git a/backend/middleware/authorizationMiddleware.js b/backend/middleware/authorizationMiddleware.js new file mode 100644 index 0000000..da599a6 --- /dev/null +++ b/backend/middleware/authorizationMiddleware.js @@ -0,0 +1,215 @@ +import permissionService from '../services/permissionService.js'; + +/** + * Authorization Middleware + * Checks if user has permission to access a resource + */ + +/** + * Check if user has permission for a specific resource and action + * @param {string} resource - Resource name (diary, members, teams, etc.) + * @param {string} action - Action type (read, write, delete) + * @returns {Function} Express middleware function + */ +export const authorize = (resource, action = 'read') => { + return async (req, res, next) => { + try { + const userId = req.user?.id; + + if (!userId) { + return res.status(401).json({ error: 'Nicht authentifiziert' }); + } + + // Get clubId from various possible sources + const clubId = + req.params.clubId ?? + req.params.clubid ?? + req.params.id ?? + req.body.clubId ?? + req.body.clubid ?? + req.query.clubId ?? + req.query.clubid; + + if (!clubId) { + return res.status(400).json({ error: 'Club-ID fehlt' }); + } + + // Check permission + const hasPermission = await permissionService.hasPermission( + userId, + parseInt(clubId), + resource, + action + ); + + if (!hasPermission) { + return res.status(403).json({ + error: 'Keine Berechtigung', + details: `Fehlende Berechtigung: ${resource}.${action}` + }); + } + + // Store permissions in request for later use + const userPermissions = await permissionService.getUserClubPermissions( + userId, + parseInt(clubId) + ); + req.userPermissions = userPermissions; + + next(); + } catch (error) { + console.error('Authorization error:', error); + res.status(500).json({ error: 'Fehler bei der Berechtigungsprüfung' }); + } + }; +}; + +/** + * Check if user is club owner + * @returns {Function} Express middleware function + */ +export const requireOwner = () => { + return async (req, res, next) => { + try { + const userId = req.user?.id; + + if (!userId) { + return res.status(401).json({ error: 'Nicht authentifiziert' }); + } + + const clubId = + req.params.clubId ?? + req.params.clubid ?? + req.params.id ?? + req.body.clubId ?? + req.body.clubid ?? + req.query.clubId ?? + req.query.clubid; + + if (!clubId) { + return res.status(400).json({ error: 'Club-ID fehlt' }); + } + + const userPermissions = await permissionService.getUserClubPermissions( + userId, + parseInt(clubId) + ); + + if (!userPermissions || !userPermissions.isOwner) { + return res.status(403).json({ + error: 'Keine Berechtigung', + details: 'Nur der Club-Ersteller hat Zugriff' + }); + } + + req.userPermissions = userPermissions; + next(); + } catch (error) { + console.error('Owner check error:', error); + res.status(500).json({ error: 'Fehler bei der Berechtigungsprüfung' }); + } + }; +}; + +/** + * Check if user is admin (owner or admin role) + * @returns {Function} Express middleware function + */ +export const requireAdmin = () => { + return async (req, res, next) => { + try { + const userId = req.user?.id; + + if (!userId) { + return res.status(401).json({ error: 'Nicht authentifiziert' }); + } + + const clubId = + req.params.clubId ?? + req.params.clubid ?? + req.params.id ?? + req.body.clubId ?? + req.body.clubid ?? + req.query.clubId ?? + req.query.clubid; + + if (!clubId) { + return res.status(400).json({ error: 'Club-ID fehlt' }); + } + + const userPermissions = await permissionService.getUserClubPermissions( + userId, + parseInt(clubId) + ); + + if (!userPermissions || (userPermissions.role !== 'admin' && !userPermissions.isOwner)) { + return res.status(403).json({ + error: 'Keine Berechtigung', + details: 'Administrator-Rechte erforderlich' + }); + } + + req.userPermissions = userPermissions; + next(); + } catch (error) { + console.error('Admin check error:', error); + res.status(500).json({ error: 'Fehler bei der Berechtigungsprüfung' }); + } + }; +}; + +/** + * Check if user has any of the specified roles + * @param {string[]} roles - Array of allowed roles + * @returns {Function} Express middleware function + */ +export const requireRole = (roles) => { + return async (req, res, next) => { + try { + const userId = req.user?.id; + + if (!userId) { + return res.status(401).json({ error: 'Nicht authentifiziert' }); + } + + const clubId = + req.params.clubId ?? + req.params.clubid ?? + req.params.id ?? + req.body.clubId ?? + req.body.clubid ?? + req.query.clubId ?? + req.query.clubid; + + if (!clubId) { + return res.status(400).json({ error: 'Club-ID fehlt' }); + } + + const userPermissions = await permissionService.getUserClubPermissions( + userId, + parseInt(clubId) + ); + + if (!userPermissions || !roles.includes(userPermissions.role)) { + return res.status(403).json({ + error: 'Keine Berechtigung', + details: `Erforderliche Rolle: ${roles.join(', ')}` + }); + } + + req.userPermissions = userPermissions; + next(); + } catch (error) { + console.error('Role check error:', error); + res.status(500).json({ error: 'Fehler bei der Berechtigungsprüfung' }); + } + }; +}; + +export default { + authorize, + requireOwner, + requireAdmin, + requireRole +}; + diff --git a/backend/middleware/requestLoggingMiddleware.js b/backend/middleware/requestLoggingMiddleware.js new file mode 100644 index 0000000..9a4dfaf --- /dev/null +++ b/backend/middleware/requestLoggingMiddleware.js @@ -0,0 +1,87 @@ +import ApiLog from '../models/ApiLog.js'; + +/** + * Middleware to log all API requests and responses + * Should be added early in the middleware chain, but after authentication + */ +export const requestLoggingMiddleware = async (req, res, next) => { + const startTime = Date.now(); + const originalSend = res.send; + + // Get request body (but limit size for sensitive data) + let requestBody = null; + if (req.body && Object.keys(req.body).length > 0) { + const bodyStr = JSON.stringify(req.body); + // Truncate very long bodies + requestBody = bodyStr.length > 10000 ? bodyStr.substring(0, 10000) + '... (truncated)' : bodyStr; + } + + // Capture response + let responseBody = null; + res.send = function(data) { + // Try to parse response as JSON + try { + const parsed = JSON.parse(data); + const responseStr = JSON.stringify(parsed); + // Truncate very long responses + responseBody = responseStr.length > 10000 ? responseStr.substring(0, 10000) + '... (truncated)' : responseStr; + } catch (e) { + // Not JSON, just use raw data (truncated) + responseBody = typeof data === 'string' ? data.substring(0, 1000) : String(data).substring(0, 1000); + } + + // Restore original send + res.send = originalSend; + return res.send.apply(res, arguments); + }; + + // Log after response is sent + res.on('finish', async () => { + const executionTime = Date.now() - startTime; + const ipAddress = req.ip || req.connection.remoteAddress || req.headers['x-forwarded-for']; + const path = req.path || req.url; + + // Nur myTischtennis-Requests loggen + // Skip logging for non-data endpoints (Status-Checks, Health-Checks, etc.) + // Exclude any endpoint containing 'status' or root paths + if ( + path.includes('/status') || + path === '/' || + path === '/health' || + path.endsWith('/status') || + path.includes('/scheduler-status') + ) { + return; + } + + // Nur myTischtennis-Endpunkte loggen (z.B. /api/mytischtennis/*) + if (!path.includes('/mytischtennis')) { + return; + } + + // Get user ID if available (wird von authMiddleware gesetzt) + const userId = req.user?.id || null; + + try { + await ApiLog.create({ + userId, + method: req.method, + path: path, + statusCode: res.statusCode, + requestBody, + responseBody, + executionTime, + errorMessage: res.statusCode >= 400 ? `HTTP ${res.statusCode}` : null, + ipAddress, + userAgent: req.headers['user-agent'], + logType: 'api_request' + }); + } catch (error) { + // Don't let logging errors break the request + console.error('Error logging API request:', error); + } + }); + + next(); +}; + diff --git a/backend/migrations/20251111_add_member_images.sql b/backend/migrations/20251111_add_member_images.sql new file mode 100644 index 0000000..884c3de --- /dev/null +++ b/backend/migrations/20251111_add_member_images.sql @@ -0,0 +1,17 @@ +-- Create table for storing multiple images per member +CREATE TABLE IF NOT EXISTS `member_image` ( + `id` INT NOT NULL AUTO_INCREMENT, + `member_id` INT NOT NULL, + `file_name` VARCHAR(255) NOT NULL, + `sort_order` INT NOT NULL DEFAULT 0, + `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + INDEX `idx_member_image_member_id` (`member_id`), + CONSTRAINT `fk_member_image_member` + FOREIGN KEY (`member_id`) + REFERENCES `member` (`id`) + ON DELETE CASCADE + ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + diff --git a/backend/migrations/add_auto_update_ratings_to_my_tischtennis.sql b/backend/migrations/add_auto_update_ratings_to_my_tischtennis.sql new file mode 100644 index 0000000..fff58b3 --- /dev/null +++ b/backend/migrations/add_auto_update_ratings_to_my_tischtennis.sql @@ -0,0 +1,13 @@ +-- Migration: Add auto update ratings fields to my_tischtennis table +-- Date: 2025-01-27 + +-- Add auto_update_ratings column +ALTER TABLE my_tischtennis +ADD COLUMN auto_update_ratings BOOLEAN NOT NULL DEFAULT FALSE; + +-- Add last_update_ratings column +ALTER TABLE my_tischtennis +ADD COLUMN last_update_ratings TIMESTAMP NULL; + +-- Create index for auto_update_ratings for efficient querying +CREATE INDEX idx_my_tischtennis_auto_update_ratings ON my_tischtennis(auto_update_ratings); diff --git a/backend/migrations/add_group_id_to_participants.sql b/backend/migrations/add_group_id_to_participants.sql new file mode 100644 index 0000000..2e6fa4c --- /dev/null +++ b/backend/migrations/add_group_id_to_participants.sql @@ -0,0 +1,9 @@ +-- Migration: Add group_id to participants table +-- This allows assigning participants to groups for training organization + +ALTER TABLE participants +ADD COLUMN group_id INTEGER NULL REFERENCES "group"(id) ON DELETE SET NULL ON UPDATE CASCADE; + +-- Add index for better query performance +CREATE INDEX IF NOT EXISTS idx_participants_group_id ON participants(group_id); + diff --git a/backend/migrations/add_match_result_fields.sql b/backend/migrations/add_match_result_fields.sql new file mode 100644 index 0000000..1671acd --- /dev/null +++ b/backend/migrations/add_match_result_fields.sql @@ -0,0 +1,28 @@ +-- Migration: Add match result fields to match table +-- Date: 2025-01-27 +-- For MariaDB + +-- Add myTischtennis meeting ID +ALTER TABLE `match` +ADD COLUMN my_tischtennis_meeting_id VARCHAR(255) NULL UNIQUE COMMENT 'Meeting ID from myTischtennis (e.g. 15440488)'; + +-- Add home match points +ALTER TABLE `match` +ADD COLUMN home_match_points INT DEFAULT 0 NULL COMMENT 'Match points won by home team'; + +-- Add guest match points +ALTER TABLE `match` +ADD COLUMN guest_match_points INT DEFAULT 0 NULL COMMENT 'Match points won by guest team'; + +-- Add is_completed flag +ALTER TABLE `match` +ADD COLUMN is_completed BOOLEAN NOT NULL DEFAULT FALSE COMMENT 'Whether the match is completed'; + +-- Add PDF URL +ALTER TABLE `match` +ADD COLUMN pdf_url VARCHAR(512) NULL COMMENT 'PDF URL from myTischtennis'; + +-- Create indexes +CREATE INDEX idx_match_my_tischtennis_meeting_id ON `match`(my_tischtennis_meeting_id); +CREATE INDEX idx_match_is_completed ON `match`(is_completed); + diff --git a/backend/migrations/add_matches_tied_to_team.sql b/backend/migrations/add_matches_tied_to_team.sql new file mode 100644 index 0000000..36ebc3d --- /dev/null +++ b/backend/migrations/add_matches_tied_to_team.sql @@ -0,0 +1,4 @@ +-- Add matches_tied column to team table +ALTER TABLE team +ADD COLUMN matches_tied INTEGER NOT NULL DEFAULT 0 AFTER matches_lost; + diff --git a/backend/migrations/add_member_contact_and_postal_code.sql b/backend/migrations/add_member_contact_and_postal_code.sql new file mode 100644 index 0000000..d291750 --- /dev/null +++ b/backend/migrations/add_member_contact_and_postal_code.sql @@ -0,0 +1,57 @@ +-- Add postal_code column to member table +ALTER TABLE `member` +ADD COLUMN `postal_code` TEXT NULL COMMENT 'Postal code (PLZ)' AFTER `city`; + +-- Create member_contact table for multiple phone numbers and email addresses +CREATE TABLE IF NOT EXISTS `member_contact` ( + `id` INT NOT NULL AUTO_INCREMENT, + `member_id` INT NOT NULL, + `type` ENUM('phone', 'email') NOT NULL COMMENT 'Type of contact: phone or email', + `value` TEXT NOT NULL, + `is_parent` BOOLEAN NOT NULL DEFAULT FALSE COMMENT 'Whether this contact belongs to a parent', + `parent_name` TEXT NULL COMMENT 'Name of the parent (e.g. "Mutter", "Vater", "Elternteil 1")', + `is_primary` BOOLEAN NOT NULL DEFAULT FALSE COMMENT 'Whether this is the primary contact of this type', + `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + INDEX `idx_member_id` (`member_id`), + INDEX `idx_type` (`type`), + CONSTRAINT `fk_member_contact_member` + FOREIGN KEY (`member_id`) + REFERENCES `member` (`id`) + ON DELETE CASCADE + ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- Migrate existing phone numbers from member.phone to member_contact +INSERT INTO `member_contact` (`member_id`, `type`, `value`, `is_parent`, `parent_name`, `is_primary`, `created_at`, `updated_at`) +SELECT + `id` AS `member_id`, + 'phone' AS `type`, + `phone` AS `value`, + FALSE AS `is_parent`, + NULL AS `parent_name`, + TRUE AS `is_primary`, + NOW() AS `created_at`, + NOW() AS `updated_at` +FROM `member` +WHERE `phone` IS NOT NULL + AND `phone` != '' + AND TRIM(`phone`) != ''; + +-- Migrate existing email addresses from member.email to member_contact +INSERT INTO `member_contact` (`member_id`, `type`, `value`, `is_parent`, `parent_name`, `is_primary`, `created_at`, `updated_at`) +SELECT + `id` AS `member_id`, + 'email' AS `type`, + `email` AS `value`, + FALSE AS `is_parent`, + NULL AS `parent_name`, + TRUE AS `is_primary`, + NOW() AS `created_at`, + NOW() AS `updated_at` +FROM `member` +WHERE `email` IS NOT NULL + AND `email` != '' + AND TRIM(`email`) != ''; + diff --git a/backend/migrations/add_mytischtennis_fields_to_league.sql b/backend/migrations/add_mytischtennis_fields_to_league.sql new file mode 100644 index 0000000..949fbb2 --- /dev/null +++ b/backend/migrations/add_mytischtennis_fields_to_league.sql @@ -0,0 +1,19 @@ +-- Migration: Add myTischtennis fields to league table +-- Date: 2025-01-27 +-- For MariaDB + +-- Add my_tischtennis_group_id column +ALTER TABLE league +ADD COLUMN my_tischtennis_group_id VARCHAR(255) NULL COMMENT 'Group ID from myTischtennis (e.g. 504417)'; + +-- Add association column +ALTER TABLE league +ADD COLUMN association VARCHAR(255) NULL COMMENT 'Association/Verband (e.g. HeTTV)'; + +-- Add groupname column +ALTER TABLE league +ADD COLUMN groupname VARCHAR(255) NULL COMMENT 'Group name for URL (e.g. 1.Kreisklasse)'; + +-- Create index for efficient querying +CREATE INDEX idx_league_my_tischtennis_group_id ON league(my_tischtennis_group_id); + diff --git a/backend/migrations/add_mytischtennis_player_id_to_member.sql b/backend/migrations/add_mytischtennis_player_id_to_member.sql new file mode 100644 index 0000000..35bf42d --- /dev/null +++ b/backend/migrations/add_mytischtennis_player_id_to_member.sql @@ -0,0 +1,11 @@ +-- Migration: Add myTischtennis player ID to member table +-- Date: 2025-01-27 +-- For MariaDB + +-- Add my_tischtennis_player_id column +ALTER TABLE member +ADD COLUMN my_tischtennis_player_id VARCHAR(255) NULL COMMENT 'Player ID from myTischtennis (e.g. NU2705037)'; + +-- Create index for efficient querying +CREATE INDEX idx_member_my_tischtennis_player_id ON member(my_tischtennis_player_id); + diff --git a/backend/migrations/add_mytischtennis_team_id_to_club_team.sql b/backend/migrations/add_mytischtennis_team_id_to_club_team.sql new file mode 100644 index 0000000..56812e6 --- /dev/null +++ b/backend/migrations/add_mytischtennis_team_id_to_club_team.sql @@ -0,0 +1,11 @@ +-- Migration: Add myTischtennis team ID to club_team table +-- Date: 2025-01-27 +-- For MariaDB + +-- Add my_tischtennis_team_id column +ALTER TABLE club_team +ADD COLUMN my_tischtennis_team_id VARCHAR(255) NULL COMMENT 'Team ID from myTischtennis (e.g. 2995094)'; + +-- Create index for efficient querying +CREATE INDEX idx_club_team_my_tischtennis_team_id ON club_team(my_tischtennis_team_id); + diff --git a/backend/migrations/add_permissions_to_user_club.sql b/backend/migrations/add_permissions_to_user_club.sql new file mode 100644 index 0000000..75d488b --- /dev/null +++ b/backend/migrations/add_permissions_to_user_club.sql @@ -0,0 +1,17 @@ +-- Add role and permissions columns to user_club table +ALTER TABLE `user_club` +ADD COLUMN `role` VARCHAR(50) DEFAULT 'member' COMMENT 'User role: admin, trainer, team_manager, member' AFTER `approved`, +ADD COLUMN `permissions` JSON NULL COMMENT 'Specific permissions: {diary: {read: true, write: true}, members: {...}, ...}' AFTER `role`, +ADD COLUMN `is_owner` BOOLEAN DEFAULT FALSE COMMENT 'True if user created the club' AFTER `permissions`; + +-- Create index for faster role lookups +CREATE INDEX `idx_user_club_role` ON `user_club` (`role`); +CREATE INDEX `idx_user_club_owner` ON `user_club` (`is_owner`); + +-- Set existing approved users as members +UPDATE `user_club` SET `role` = 'member' WHERE `approved` = 1 AND `role` IS NULL; + +-- If there's a user who created the club (we need to identify them somehow) +-- For now, we'll need to manually set the owner after migration + + diff --git a/backend/migrations/add_player_tracking_to_match.sql b/backend/migrations/add_player_tracking_to_match.sql new file mode 100644 index 0000000..b1a93f6 --- /dev/null +++ b/backend/migrations/add_player_tracking_to_match.sql @@ -0,0 +1,8 @@ +-- Add player tracking fields to match table +-- These fields store arrays of member IDs for different participation states + +ALTER TABLE `match` +ADD COLUMN `players_ready` JSON NULL COMMENT 'Array of member IDs who are ready to play' AFTER `pdf_url`, +ADD COLUMN `players_planned` JSON NULL COMMENT 'Array of member IDs who are planned to play' AFTER `players_ready`, +ADD COLUMN `players_played` JSON NULL COMMENT 'Array of member IDs who actually played' AFTER `players_planned`; + diff --git a/backend/migrations/add_table_fields_to_team.sql b/backend/migrations/add_table_fields_to_team.sql new file mode 100644 index 0000000..b1d7674 --- /dev/null +++ b/backend/migrations/add_table_fields_to_team.sql @@ -0,0 +1,11 @@ +-- Migration: Add table fields to team table +-- Add fields for league table calculations + +ALTER TABLE team ADD COLUMN matches_played INT NOT NULL DEFAULT 0; +ALTER TABLE team ADD COLUMN matches_won INT NOT NULL DEFAULT 0; +ALTER TABLE team ADD COLUMN matches_lost INT NOT NULL DEFAULT 0; +ALTER TABLE team ADD COLUMN sets_won INT NOT NULL DEFAULT 0; +ALTER TABLE team ADD COLUMN sets_lost INT NOT NULL DEFAULT 0; +ALTER TABLE team ADD COLUMN points_won INT NOT NULL DEFAULT 0; +ALTER TABLE team ADD COLUMN points_lost INT NOT NULL DEFAULT 0; +ALTER TABLE team ADD COLUMN table_points INT NOT NULL DEFAULT 0; diff --git a/backend/migrations/add_table_points_won_lost_to_team.sql b/backend/migrations/add_table_points_won_lost_to_team.sql new file mode 100644 index 0000000..67f05fe --- /dev/null +++ b/backend/migrations/add_table_points_won_lost_to_team.sql @@ -0,0 +1,5 @@ +-- Add table_points_won and table_points_lost columns to team table +ALTER TABLE team +ADD COLUMN table_points_won INTEGER NOT NULL DEFAULT 0 AFTER table_points, +ADD COLUMN table_points_lost INTEGER NOT NULL DEFAULT 0 AFTER table_points_won; + diff --git a/backend/migrations/create_api_log_table.sql b/backend/migrations/create_api_log_table.sql new file mode 100644 index 0000000..337d005 --- /dev/null +++ b/backend/migrations/create_api_log_table.sql @@ -0,0 +1,26 @@ +-- Migration: Create api_log table for comprehensive request/response and execution logging + +CREATE TABLE IF NOT EXISTS api_log ( + id INT AUTO_INCREMENT PRIMARY KEY, + user_id INT NULL, + method VARCHAR(10) NOT NULL COMMENT 'HTTP method (GET, POST, PUT, DELETE, etc.)', + path VARCHAR(500) NOT NULL COMMENT 'Request path', + status_code INT NULL COMMENT 'HTTP status code', + request_body TEXT NULL COMMENT 'Request body (truncated if too long)', + response_body TEXT NULL COMMENT 'Response body (truncated if too long)', + execution_time INT NULL COMMENT 'Execution time in milliseconds', + error_message TEXT NULL COMMENT 'Error message if request failed', + ip_address VARCHAR(45) NULL COMMENT 'Client IP address', + user_agent VARCHAR(500) NULL COMMENT 'User agent string', + log_type ENUM('api_request', 'scheduler', 'cron_job', 'manual') NOT NULL DEFAULT 'api_request' COMMENT 'Type of log entry', + scheduler_job_type VARCHAR(50) NULL COMMENT 'Type of scheduler job (rating_updates, match_results, etc.)', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + FOREIGN KEY (user_id) REFERENCES user(id) ON DELETE SET NULL ON UPDATE CASCADE, + INDEX idx_api_log_user_id (user_id, created_at), + INDEX idx_api_log_path (path, created_at), + INDEX idx_api_log_log_type (log_type, created_at), + INDEX idx_api_log_created_at (created_at), + INDEX idx_api_log_status_code (status_code) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + diff --git a/backend/migrations/create_my_tischtennis_fetch_log.sql b/backend/migrations/create_my_tischtennis_fetch_log.sql new file mode 100644 index 0000000..a37f271 --- /dev/null +++ b/backend/migrations/create_my_tischtennis_fetch_log.sql @@ -0,0 +1,20 @@ +-- Create my_tischtennis_fetch_log table for tracking data fetches +CREATE TABLE IF NOT EXISTS my_tischtennis_fetch_log ( + id INT AUTO_INCREMENT PRIMARY KEY, + user_id INT NOT NULL, + fetch_type ENUM('ratings', 'match_results', 'league_table') NOT NULL COMMENT 'Type of data fetch', + success BOOLEAN NOT NULL DEFAULT FALSE, + message TEXT, + error_details TEXT, + records_processed INT NOT NULL DEFAULT 0 COMMENT 'Number of records processed', + execution_time INT COMMENT 'Execution time in milliseconds', + is_automatic BOOLEAN NOT NULL DEFAULT FALSE COMMENT 'Automatic or manual fetch', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + + FOREIGN KEY (user_id) REFERENCES user(id) ON DELETE CASCADE ON UPDATE CASCADE, + + INDEX idx_user_fetch_type_created (user_id, fetch_type, created_at), + INDEX idx_created_at (created_at) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + diff --git a/backend/migrations/create_my_tischtennis_update_history.sql b/backend/migrations/create_my_tischtennis_update_history.sql new file mode 100644 index 0000000..72f652d --- /dev/null +++ b/backend/migrations/create_my_tischtennis_update_history.sql @@ -0,0 +1,23 @@ +-- Migration: Create my_tischtennis_update_history table +-- Date: 2025-01-27 +-- For MariaDB + +CREATE TABLE IF NOT EXISTS my_tischtennis_update_history ( + id INT AUTO_INCREMENT PRIMARY KEY, + user_id INT NOT NULL, + success BOOLEAN NOT NULL DEFAULT FALSE, + message TEXT, + error_details TEXT, + updated_count INT DEFAULT 0, + execution_time INT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + + CONSTRAINT fk_my_tischtennis_update_history_user_id + FOREIGN KEY (user_id) REFERENCES user(id) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- Create indexes for efficient querying +CREATE INDEX idx_my_tischtennis_update_history_user_id ON my_tischtennis_update_history(user_id); +CREATE INDEX idx_my_tischtennis_update_history_created_at ON my_tischtennis_update_history(created_at); +CREATE INDEX idx_my_tischtennis_update_history_success ON my_tischtennis_update_history(success); diff --git a/backend/migrations/make_location_optional_in_match.sql b/backend/migrations/make_location_optional_in_match.sql new file mode 100644 index 0000000..cb7e62a --- /dev/null +++ b/backend/migrations/make_location_optional_in_match.sql @@ -0,0 +1,8 @@ +-- Migration: Make locationId optional in match table +-- Date: 2025-01-27 +-- For MariaDB + +-- Modify locationId to allow NULL +ALTER TABLE `match` +MODIFY COLUMN location_id INT NULL; + diff --git a/backend/migrations/update_existing_user_club_permissions.sql b/backend/migrations/update_existing_user_club_permissions.sql new file mode 100644 index 0000000..0eee5cb --- /dev/null +++ b/backend/migrations/update_existing_user_club_permissions.sql @@ -0,0 +1,38 @@ +-- Update existing user_club entries with default permissions +-- This migration sets default values for role and is_owner for existing club memberships + +-- Set default role to 'member' for all approved users who don't have a role yet +UPDATE `user_club` +SET `role` = 'member' +WHERE `approved` = 1 + AND (`role` IS NULL OR `role` = ''); + +-- Optionally: Set the first approved user of each club as owner +-- This finds the user with the lowest user_id per club (oldest member) and marks them as owner +UPDATE `user_club` AS uc1 +INNER JOIN ( + SELECT `club_id`, MIN(`user_id`) as `first_user_id` + FROM `user_club` + WHERE `approved` = 1 + GROUP BY `club_id` +) AS uc2 ON uc1.`club_id` = uc2.`club_id` AND uc1.`user_id` = uc2.`first_user_id` +SET + uc1.`is_owner` = 1, + uc1.`role` = 'admin'; + +-- Verify the changes +SELECT + uc.`club_id`, + c.`name` as club_name, + uc.`user_id`, + u.`email` as user_email, + uc.`role`, + uc.`is_owner`, + uc.`approved` +FROM `user_club` uc +LEFT JOIN `club` c ON c.`id` = uc.`club_id` +LEFT JOIN `user` u ON u.`id` = uc.`user_id` +WHERE uc.`approved` = 1 +ORDER BY uc.`club_id`, uc.`is_owner` DESC, uc.`user_id`; + + diff --git a/backend/models/ApiLog.js b/backend/models/ApiLog.js new file mode 100644 index 0000000..3313fbf --- /dev/null +++ b/backend/models/ApiLog.js @@ -0,0 +1,102 @@ +import { DataTypes } from 'sequelize'; +import sequelize from '../database.js'; +import User from './User.js'; + +const ApiLog = sequelize.define('ApiLog', { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + allowNull: false, + }, + userId: { + type: DataTypes.INTEGER, + allowNull: true, + references: { + model: User, + key: 'id', + }, + onDelete: 'SET NULL', + onUpdate: 'CASCADE', + }, + method: { + type: DataTypes.STRING(10), + allowNull: false, + comment: 'HTTP method (GET, POST, PUT, DELETE, etc.)' + }, + path: { + type: DataTypes.STRING(500), + allowNull: false, + comment: 'Request path' + }, + statusCode: { + type: DataTypes.INTEGER, + allowNull: true, + comment: 'HTTP status code' + }, + requestBody: { + type: DataTypes.TEXT, + allowNull: true, + comment: 'Request body (truncated if too long)' + }, + responseBody: { + type: DataTypes.TEXT, + allowNull: true, + comment: 'Response body (truncated if too long)' + }, + executionTime: { + type: DataTypes.INTEGER, + allowNull: true, + comment: 'Execution time in milliseconds' + }, + errorMessage: { + type: DataTypes.TEXT, + allowNull: true, + comment: 'Error message if completes failed' + }, + ipAddress: { + type: DataTypes.STRING(45), + allowNull: true, + comment: 'Client IP address' + }, + userAgent: { + type: DataTypes.STRING(500), + allowNull: true, + comment: 'User agent string' + }, + logType: { + type: DataTypes.ENUM('api_request', 'scheduler', 'cron_job', 'manual'), + allowNull: false, + defaultValue: 'api_request', + comment: 'Type of log entry' + }, + schedulerJobType: { + type: DataTypes.STRING(50), + allowNull: true, + comment: 'Type of scheduler job (rating_updates, match_results, etc.)' + }, +}, { + underscored: true, + tableName: 'api_log', + timestamps: true, + indexes: [ + { + fields: ['user_id', 'created_at'] + }, + { + fields: ['path', 'created_at'] + }, + { + fields: ['log_type', 'created_at'] + }, + { + fields: ['created_at'] + }, + { + fields: ['status_code'] + } + ] +}); + +export default ApiLog; + diff --git a/backend/models/ClubTeam.js b/backend/models/ClubTeam.js index fb84cc1..412268e 100644 --- a/backend/models/ClubTeam.js +++ b/backend/models/ClubTeam.js @@ -45,6 +45,12 @@ const ClubTeam = sequelize.define('ClubTeam', { onDelete: 'CASCADE', onUpdate: 'CASCADE', }, + myTischtennisTeamId: { + type: DataTypes.STRING, + allowNull: true, + comment: 'Team ID from myTischtennis (e.g. 2995094)', + field: 'my_tischtennis_team_id' + }, }, { underscored: true, tableName: 'club_team', diff --git a/backend/models/League.js b/backend/models/League.js index 12c8ac7..54b0e6b 100644 --- a/backend/models/League.js +++ b/backend/models/League.js @@ -34,6 +34,22 @@ const League = sequelize.define('League', { onDelete: 'CASCADE', onUpdate: 'CASCADE', }, + myTischtennisGroupId: { + type: DataTypes.STRING, + allowNull: true, + comment: 'Group ID from myTischtennis (e.g. 504417)', + field: 'my_tischtennis_group_id' + }, + association: { + type: DataTypes.STRING, + allowNull: true, + comment: 'Association/Verband (e.g. HeTTV)', + }, + groupname: { + type: DataTypes.STRING, + allowNull: true, + comment: 'Group name for URL (e.g. 1.Kreisklasse)', + }, }, { underscored: true, tableName: 'league', diff --git a/backend/models/Match.js b/backend/models/Match.js index ee385e1..591bbac 100644 --- a/backend/models/Match.js +++ b/backend/models/Match.js @@ -26,7 +26,7 @@ const Match = sequelize.define('Match', { model: Location, key: 'id', }, - allowNull: false, + allowNull: true, }, homeTeamId: { type: DataTypes.INTEGER, @@ -75,6 +75,58 @@ const Match = sequelize.define('Match', { allowNull: true, comment: 'Pin-Code für Gastteam aus PDF-Parsing' }, + myTischtennisMeetingId: { + type: DataTypes.STRING, + allowNull: true, + unique: true, + comment: 'Meeting ID from myTischtennis (e.g. 15440488)', + field: 'my_tischtennis_meeting_id' + }, + homeMatchPoints: { + type: DataTypes.INTEGER, + allowNull: true, + defaultValue: 0, + comment: 'Match points won by home team', + field: 'home_match_points' + }, + guestMatchPoints: { + type: DataTypes.INTEGER, + allowNull: true, + defaultValue: 0, + comment: 'Match points won by guest team', + field: 'guest_match_points' + }, + isCompleted: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false, + comment: 'Whether the match is completed', + field: 'is_completed' + }, + pdfUrl: { + type: DataTypes.STRING, + allowNull: true, + comment: 'PDF URL from myTischtennis', + field: 'pdf_url' + }, + playersReady: { + type: DataTypes.JSON, + allowNull: true, + comment: 'Array of member IDs who are ready to play', + field: 'players_ready' + }, + playersPlanned: { + type: DataTypes.JSON, + allowNull: true, + comment: 'Array of member IDs who are planned to play', + field: 'players_planned' + }, + playersPlayed: { + type: DataTypes.JSON, + allowNull: true, + comment: 'Array of member IDs who actually played', + field: 'players_played' + }, }, { underscored: true, tableName: 'match', diff --git a/backend/models/Member.js b/backend/models/Member.js index 2c128ee..e9616b7 100644 --- a/backend/models/Member.js +++ b/backend/models/Member.js @@ -45,13 +45,14 @@ const Member = sequelize.define('Member', { }, birthDate: { type: DataTypes.STRING, - allowNull: false, + allowNull: true, set(value) { - const encryptedValue = encryptData(value); + const encryptedValue = encryptData(value || ''); this.setDataValue('birthDate', encryptedValue); }, get() { const encryptedValue = this.getDataValue('birthDate'); + if (!encryptedValue) return null; return decryptData(encryptedValue); } }, @@ -91,6 +92,21 @@ const Member = sequelize.define('Member', { return decryptData(encryptedValue); } }, + postalCode: { + type: DataTypes.STRING, + allowNull: true, + set(value) { + const encryptedValue = encryptData(value || ''); + this.setDataValue('postalCode', encryptedValue); + }, + get() { + const encryptedValue = this.getDataValue('postalCode'); + if (!encryptedValue) return null; + return decryptData(encryptedValue); + }, + field: 'postal_code', + comment: 'Postal code (PLZ)' + }, email: { type: DataTypes.STRING, allowNull: false, @@ -137,6 +153,19 @@ const Member = sequelize.define('Member', { type: DataTypes.INTEGER, allowNull: true, defaultValue: null + }, + memberFormHandedOver: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false, + field: 'member_form_handed_over', + comment: 'Mitgliedsformular ausgehändigt' + }, + myTischtennisPlayerId: { + type: DataTypes.STRING, + allowNull: true, + comment: 'Player ID from myTischtennis (e.g. NU2705037)', + field: 'my_tischtennis_player_id' } }, { underscored: true, @@ -151,13 +180,7 @@ const Member = sequelize.define('Member', { member.save(); }, } -}, - { - underscored: true, - tableName: 'log', - timestamps: true - } -); +}); Member.belongsTo(Club, { as: 'club' }); Club.hasMany(Member, { as: 'members' }); diff --git a/backend/models/MemberContact.js b/backend/models/MemberContact.js new file mode 100644 index 0000000..0425b86 --- /dev/null +++ b/backend/models/MemberContact.js @@ -0,0 +1,89 @@ +import { DataTypes } from 'sequelize'; +import sequelize from '../database.js'; +import Member from './Member.js'; +import { encryptData, decryptData } from '../utils/encrypt.js'; + +const MemberContact = sequelize.define('MemberContact', { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + allowNull: false + }, + memberId: { + type: DataTypes.INTEGER, + allowNull: false, + references: { + model: 'member', + key: 'id' + }, + onDelete: 'CASCADE', + field: 'member_id' + }, + type: { + type: DataTypes.ENUM('phone', 'email'), + allowNull: false, + comment: 'Type of contact: phone or email' + }, + value: { + type: DataTypes.STRING, + allowNull: false, + set(value) { + const encryptedValue = encryptData(value); + this.setDataValue('value', encryptedValue); + }, + get() { + const encryptedValue = this.getDataValue('value'); + if (!encryptedValue) return null; + try { + return decryptData(encryptedValue); + } catch (error) { + console.error('[MemberContact] Error decrypting value:', error); + return encryptedValue; // Fallback: return encrypted value if decryption fails + } + } + }, + isParent: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false, + field: 'is_parent', + comment: 'Whether this contact belongs to a parent' + }, + parentName: { + type: DataTypes.STRING, + allowNull: true, + set(value) { + if (value) { + const encryptedValue = encryptData(value); + this.setDataValue('parentName', encryptedValue); + } else { + this.setDataValue('parentName', null); + } + }, + get() { + const encryptedValue = this.getDataValue('parentName'); + return encryptedValue ? decryptData(encryptedValue) : null; + }, + field: 'parent_name', + comment: 'Name of the parent (e.g. "Mutter", "Vater", "Elternteil 1")' + }, + isPrimary: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false, + field: 'is_primary', + comment: 'Whether this is the primary contact of this type' + } +}, { + underscored: true, + sequelize, + modelName: 'MemberContact', + tableName: 'member_contact', + timestamps: true +}); + +// Associations are defined in models/index.js to avoid duplicate alias errors + +export default MemberContact; + diff --git a/backend/models/MemberImage.js b/backend/models/MemberImage.js new file mode 100644 index 0000000..a984b90 --- /dev/null +++ b/backend/models/MemberImage.js @@ -0,0 +1,40 @@ +import { DataTypes } from 'sequelize'; +import sequelize from '../database.js'; + +const MemberImage = sequelize.define('MemberImage', { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + memberId: { + type: DataTypes.INTEGER, + allowNull: false, + field: 'member_id', + references: { + model: 'member', + key: 'id' + }, + onDelete: 'CASCADE', + onUpdate: 'CASCADE' + }, + fileName: { + type: DataTypes.STRING(255), + allowNull: false, + field: 'file_name' + }, + sortOrder: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0, + field: 'sort_order' + } +}, { + tableName: 'member_image', + underscored: true, + timestamps: true +}); + +export default MemberImage; + diff --git a/backend/models/MemberTransferConfig.js b/backend/models/MemberTransferConfig.js new file mode 100644 index 0000000..b790aeb --- /dev/null +++ b/backend/models/MemberTransferConfig.js @@ -0,0 +1,117 @@ +import { DataTypes } from 'sequelize'; +import sequelize from '../database.js'; +import Club from './Club.js'; +import { encryptData, decryptData } from '../utils/encrypt.js'; + +const MemberTransferConfig = sequelize.define('MemberTransferConfig', { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + allowNull: false + }, + clubId: { + type: DataTypes.INTEGER, + allowNull: false, + unique: true, + references: { + model: Club, + key: 'id' + }, + onDelete: 'CASCADE' + }, + server: { + type: DataTypes.STRING, + allowNull: true, + field: 'server', + comment: 'Base URL des Servers (z.B. https://example.com)' + }, + loginEndpoint: { + type: DataTypes.STRING, + allowNull: true, + field: 'login_endpoint', + comment: 'Relativer Pfad zum Login-Endpoint (z.B. /api/auth/login)' + }, + loginFormat: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: 'json', + field: 'login_format' + }, + encryptedLoginCredentials: { + type: DataTypes.TEXT, + allowNull: true, + field: 'encrypted_login_credentials', + comment: 'Verschlüsselte Login-Daten als JSON-String' + }, + transferEndpoint: { + type: DataTypes.STRING, + allowNull: false, + field: 'transfer_endpoint', + comment: 'Relativer Pfad zum Übertragungs-Endpoint (z.B. /api/members/bulk)' + }, + transferMethod: { + type: DataTypes.STRING, + allowNull: false, + defaultValue: 'POST', + field: 'transfer_method' + }, + transferFormat: { + type: DataTypes.STRING, + allowNull: false, + defaultValue: 'json', + field: 'transfer_format' + }, + transferTemplate: { + type: DataTypes.TEXT, + allowNull: false, + field: 'transfer_template' + }, + useBulkMode: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false, + field: 'use_bulk_mode' + }, + bulkWrapperTemplate: { + type: DataTypes.TEXT, + allowNull: true, + field: 'bulk_wrapper_template', + comment: 'Optionales Template für die äußere Struktur im Bulk-Modus (z.B. {"data": {"members": "{{members}}"}})' + } +}, { + underscored: true, + tableName: 'member_transfer_config', + timestamps: true +}); + +// Getter/Setter für verschlüsselte Login-Daten +MemberTransferConfig.prototype.getLoginCredentials = function() { + if (!this.encryptedLoginCredentials) { + return null; + } + try { + const decrypted = decryptData(this.encryptedLoginCredentials); + return JSON.parse(decrypted); + } catch (error) { + console.error('[MemberTransferConfig] Error decrypting login credentials:', error); + return null; + } +}; + +MemberTransferConfig.prototype.setLoginCredentials = function(credentials) { + if (!credentials || Object.keys(credentials).length === 0) { + this.encryptedLoginCredentials = null; + return; + } + try { + const jsonString = JSON.stringify(credentials); + this.encryptedLoginCredentials = encryptData(jsonString); + } catch (error) { + console.error('[MemberTransferConfig] Error encrypting login credentials:', error); + this.encryptedLoginCredentials = null; + } +}; + +export default MemberTransferConfig; + diff --git a/backend/models/MyTischtennis.js b/backend/models/MyTischtennis.js index 5517249..433a325 100644 --- a/backend/models/MyTischtennis.js +++ b/backend/models/MyTischtennis.js @@ -34,6 +34,12 @@ const MyTischtennis = sequelize.define('MyTischtennis', { allowNull: false, field: 'save_password' }, + autoUpdateRatings: { + type: DataTypes.BOOLEAN, + defaultValue: false, + allowNull: false, + field: 'auto_update_ratings' + }, accessToken: { type: DataTypes.TEXT, allowNull: true, @@ -82,6 +88,11 @@ const MyTischtennis = sequelize.define('MyTischtennis', { type: DataTypes.DATE, allowNull: true, field: 'last_login_success' + }, + lastUpdateRatings: { + type: DataTypes.DATE, + allowNull: true, + field: 'last_update_ratings' } }, { underscored: true, diff --git a/backend/models/MyTischtennisFetchLog.js b/backend/models/MyTischtennisFetchLog.js new file mode 100644 index 0000000..0197fa8 --- /dev/null +++ b/backend/models/MyTischtennisFetchLog.js @@ -0,0 +1,72 @@ +import { DataTypes } from 'sequelize'; +import sequelize from '../database.js'; +import User from './User.js'; + +const MyTischtennisFetchLog = sequelize.define('MyTischtennisFetchLog', { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + allowNull: false, + }, + userId: { + type: DataTypes.INTEGER, + allowNull: false, + references: { + model: User, + key: 'id', + }, + onDelete: 'CASCADE', + onUpdate: 'CASCADE', + }, + fetchType: { + type: DataTypes.ENUM('ratings', 'match_results', 'league_table'), + allowNull: false, + comment: 'Type of data fetch: ratings, match_results, or league_table' + }, + success: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + message: { + type: DataTypes.TEXT, + allowNull: true, + }, + errorDetails: { + type: DataTypes.TEXT, + allowNull: true, + }, + recordsProcessed: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0, + comment: 'Number of records processed (e.g., players updated, matches fetched)' + }, + executionTime: { + type: DataTypes.INTEGER, + allowNull: true, + comment: 'Execution time in milliseconds' + }, + isAutomatic: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false, + comment: 'Whether this was an automatic or manual fetch' + }, +}, { + underscored: true, + tableName: 'my_tischtennis_fetch_log', + timestamps: true, + indexes: [ + { + fields: ['user_id', 'fetch_type', 'created_at'] + }, + { + fields: ['created_at'] + } + ] +}); + +export default MyTischtennisFetchLog; + diff --git a/backend/models/MyTischtennisUpdateHistory.js b/backend/models/MyTischtennisUpdateHistory.js new file mode 100644 index 0000000..780b168 --- /dev/null +++ b/backend/models/MyTischtennisUpdateHistory.js @@ -0,0 +1,63 @@ +import { DataTypes } from 'sequelize'; +import sequelize from '../database.js'; + +const MyTischtennisUpdateHistory = sequelize.define('MyTischtennisUpdateHistory', { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + allowNull: false + }, + userId: { + type: DataTypes.INTEGER, + allowNull: false, + references: { + model: 'user', + key: 'id' + }, + onDelete: 'CASCADE' + }, + success: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false + }, + message: { + type: DataTypes.TEXT, + allowNull: true + }, + errorDetails: { + type: DataTypes.TEXT, + allowNull: true, + field: 'error_details' + }, + updatedCount: { + type: DataTypes.INTEGER, + allowNull: true, + defaultValue: 0, + field: 'updated_count' + }, + executionTime: { + type: DataTypes.INTEGER, + allowNull: true, + comment: 'Execution time in milliseconds', + field: 'execution_time' + } +}, { + underscored: true, + tableName: 'my_tischtennis_update_history', + timestamps: true, + indexes: [ + { + fields: ['user_id'] + }, + { + fields: ['created_at'] + }, + { + fields: ['success'] + } + ] +}); + +export default MyTischtennisUpdateHistory; diff --git a/backend/models/Participant.js b/backend/models/Participant.js index 5bbcb85..b5438b5 100644 --- a/backend/models/Participant.js +++ b/backend/models/Participant.js @@ -2,6 +2,7 @@ import { DataTypes } from 'sequelize'; import sequelize from '../database.js'; import Member from './Member.js'; import DiaryDate from './DiaryDates.js'; +import Group from './Group.js'; import { encryptData, decryptData } from '../utils/encrypt.js'; const Participant = sequelize.define('Participant', { @@ -27,6 +28,16 @@ const Participant = sequelize.define('Participant', { key: 'id' } }, + groupId: { + type: DataTypes.INTEGER, + allowNull: true, + references: { + model: Group, + key: 'id' + }, + onDelete: 'SET NULL', + onUpdate: 'CASCADE' + }, notes: { type: DataTypes.STRING(4096), allowNull: true, diff --git a/backend/models/Team.js b/backend/models/Team.js index 781231e..cfd1126 100644 --- a/backend/models/Team.js +++ b/backend/models/Team.js @@ -45,6 +45,62 @@ const Team = sequelize.define('Team', { onDelete: 'CASCADE', onUpdate: 'CASCADE', }, + // Tabellenfelder + matchesPlayed: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0, + }, + matchesWon: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0, + }, + matchesLost: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0, + }, + matchesTied: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0, + }, + setsWon: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0, + }, + setsLost: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0, + }, + pointsWon: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0, + }, + pointsLost: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0, + }, + tablePoints: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0, + }, + tablePointsWon: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0, + }, + tablePointsLost: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0, + }, }, { underscored: true, tableName: 'team', diff --git a/backend/models/UserClub.js b/backend/models/UserClub.js index e4f5898..b626fa4 100644 --- a/backend/models/UserClub.js +++ b/backend/models/UserClub.js @@ -6,6 +6,7 @@ import Club from './Club.js'; const UserClub = sequelize.define('UserClub', { userId: { type: DataTypes.INTEGER, + primaryKey: true, references: { model: User, key: 'id', @@ -13,6 +14,7 @@ const UserClub = sequelize.define('UserClub', { }, clubId: { type: DataTypes.INTEGER, + primaryKey: true, references: { model: Club, key: 'id', @@ -22,6 +24,23 @@ const UserClub = sequelize.define('UserClub', { type: DataTypes.BOOLEAN, defaultValue: false, }, + role: { + type: DataTypes.STRING(50), + defaultValue: 'member', + allowNull: false, + comment: 'User role: admin, trainer, team_manager, member' + }, + permissions: { + type: DataTypes.JSON, + allowNull: true, + comment: 'Specific permissions: {diary: {read: true, write: true}, members: {...}, ...}' + }, + isOwner: { + type: DataTypes.BOOLEAN, + defaultValue: false, + allowNull: false, + comment: 'True if user created the club' + } }, { underscored: true, tableName: 'user_club', diff --git a/backend/models/index.js b/backend/models/index.js index 73e14f7..217421a 100644 --- a/backend/models/index.js +++ b/backend/models/index.js @@ -36,6 +36,12 @@ import OfficialTournament from './OfficialTournament.js'; import OfficialCompetition from './OfficialCompetition.js'; import OfficialCompetitionMember from './OfficialCompetitionMember.js'; import MyTischtennis from './MyTischtennis.js'; +import MyTischtennisUpdateHistory from './MyTischtennisUpdateHistory.js'; +import MyTischtennisFetchLog from './MyTischtennisFetchLog.js'; +import ApiLog from './ApiLog.js'; +import MemberTransferConfig from './MemberTransferConfig.js'; +import MemberContact from './MemberContact.js'; +import MemberImage from './MemberImage.js'; // Official tournaments relations OfficialTournament.hasMany(OfficialCompetition, { foreignKey: 'tournamentId', as: 'competitions' }); OfficialCompetition.belongsTo(OfficialTournament, { foreignKey: 'tournamentId', as: 'tournament' }); @@ -120,6 +126,9 @@ Team.belongsTo(Club, { foreignKey: 'clubId', as: 'club' }); Club.hasMany(League, { foreignKey: 'clubId', as: 'leagues' }); League.belongsTo(Club, { foreignKey: 'clubId', as: 'club' }); +Season.hasMany(League, { foreignKey: 'seasonId', as: 'leagues' }); +League.belongsTo(Season, { foreignKey: 'seasonId', as: 'season' }); + League.hasMany(Team, { foreignKey: 'leagueId', as: 'teams' }); Team.belongsTo(League, { foreignKey: 'leagueId', as: 'league' }); @@ -155,7 +164,7 @@ Club.hasMany(UserClub, { foreignKey: 'clubId' }); Group.belongsTo(DiaryDate, { foreignKey: 'diaryDateId', as: 'diaryDateGroup' }); DiaryDate.hasMany(Group, { foreignKey: 'diaryDateId', as: 'groupsDiaryDate' }); -GroupActivity.belongsTo(DiaryDateActivity, { foreignKey: 'id', as: 'activityGroupActivity' }); +GroupActivity.belongsTo(DiaryDateActivity, { foreignKey: 'diaryDateActivity', as: 'activityGroupActivity' }); DiaryDateActivity.hasMany(GroupActivity, { foreignKey: 'diaryDateActivity', as: 'groupActivities' }); Group.hasOne(GroupActivity, { foreignKey: 'groupId', as: 'groupGroupActivity' }); @@ -227,6 +236,24 @@ DiaryDate.hasMany(Accident, { foreignKey: 'diaryDateId', as: 'accidents' }); User.hasOne(MyTischtennis, { foreignKey: 'userId', as: 'myTischtennis' }); MyTischtennis.belongsTo(User, { foreignKey: 'userId', as: 'user' }); +User.hasMany(MyTischtennisUpdateHistory, { foreignKey: 'userId', as: 'updateHistory' }); +MyTischtennisUpdateHistory.belongsTo(User, { foreignKey: 'userId', as: 'user' }); + +User.hasMany(MyTischtennisFetchLog, { foreignKey: 'userId', as: 'fetchLogs' }); +MyTischtennisFetchLog.belongsTo(User, { foreignKey: 'userId', as: 'user' }); + +User.hasMany(ApiLog, { foreignKey: 'userId', as: 'apiLogs' }); +ApiLog.belongsTo(User, { foreignKey: 'userId', as: 'user' }); + +Club.hasOne(MemberTransferConfig, { foreignKey: 'clubId', as: 'memberTransferConfig' }); +MemberTransferConfig.belongsTo(Club, { foreignKey: 'clubId', as: 'club' }); + +Member.hasMany(MemberContact, { foreignKey: 'memberId', as: 'contacts' }); +MemberContact.belongsTo(Member, { foreignKey: 'memberId', as: 'member' }); + +Member.hasMany(MemberImage, { foreignKey: 'memberId', as: 'images' }); +MemberImage.belongsTo(Member, { foreignKey: 'memberId', as: 'member' }); + export { User, Log, @@ -265,4 +292,10 @@ export { OfficialCompetition, OfficialCompetitionMember, MyTischtennis, + MyTischtennisUpdateHistory, + MyTischtennisFetchLog, + ApiLog, + MemberTransferConfig, + MemberContact, + MemberImage, }; diff --git a/backend/node_modules/.package-lock.json b/backend/node_modules/.package-lock.json index 4d9c84e..6da0403 100644 --- a/backend/node_modules/.package-lock.json +++ b/backend/node_modules/.package-lock.json @@ -6,29 +6,30 @@ "packages": { "node_modules/@babel/runtime": { "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/@emnapi/runtime": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.2.0.tgz", - "integrity": "sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==", - "ideallyInert": true, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", "optional": true, - "dependencies": { - "tslib": "^2.4.0" + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "eslint-visitor-keys": "^3.3.0" @@ -42,9 +43,8 @@ }, "node_modules/@eslint-community/eslint-utils/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", "peer": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -55,9 +55,8 @@ }, "node_modules/@eslint-community/regexpp": { "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" @@ -65,9 +64,8 @@ }, "node_modules/@eslint/config-array": { "version": "0.17.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.1.tgz", - "integrity": "sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==", "dev": true, + "license": "Apache-2.0", "peer": true, "dependencies": { "@eslint/object-schema": "^2.1.4", @@ -80,9 +78,8 @@ }, "node_modules/@eslint/config-array/node_modules/debug": { "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "ms": "2.1.2" @@ -98,16 +95,14 @@ }, "node_modules/@eslint/config-array/node_modules/ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/@eslint/eslintrc": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", - "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "ajv": "^6.12.4", @@ -129,9 +124,8 @@ }, "node_modules/@eslint/eslintrc/node_modules/debug": { "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "ms": "2.1.2" @@ -147,16 +141,14 @@ }, "node_modules/@eslint/eslintrc/node_modules/ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/@eslint/js": { "version": "9.9.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.9.0.tgz", - "integrity": "sha512-hhetes6ZHP3BlXLxmd8K2SNgkhNSi+UcecbnwWKwpP7kyi/uC75DJ1lOOBO3xrC4jyojtGE3YxKZPHfk4yrgug==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -164,19 +156,23 @@ }, "node_modules/@eslint/object-schema": { "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", - "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", "dev": true, + "license": "Apache-2.0", "peer": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "dev": true, + "license": "MIT", + "optional": true + }, "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", "peer": true, "engines": { "node": ">=12.22" @@ -188,9 +184,8 @@ }, "node_modules/@humanwhocodes/retry": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", - "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", "dev": true, + "license": "Apache-2.0", "peer": true, "engines": { "node": ">=18.18" @@ -200,141 +195,8 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@img/sharp-darwin-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", - "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", - "cpu": [ - "arm64" - ], - "ideallyInert": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.0.4" - } - }, - "node_modules/@img/sharp-darwin-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", - "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", - "cpu": [ - "x64" - ], - "ideallyInert": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.0.4" - } - }, - "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", - "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", - "cpu": [ - "arm64" - ], - "ideallyInert": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", - "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", - "cpu": [ - "x64" - ], - "ideallyInert": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", - "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", - "cpu": [ - "arm" - ], - "ideallyInert": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", - "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", - "cpu": [ - "arm64" - ], - "ideallyInert": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", - "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", - "cpu": [ - "s390x" - ], - "ideallyInert": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, "node_modules/@img/sharp-libvips-linux-x64": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", - "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", "cpu": [ "x64" ], @@ -347,27 +209,8 @@ "url": "https://opencollective.com/libvips" } }, - "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", - "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", - "cpu": [ - "arm64" - ], - "ideallyInert": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, "node_modules/@img/sharp-libvips-linuxmusl-x64": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", - "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", "cpu": [ "x64" ], @@ -380,79 +223,8 @@ "url": "https://opencollective.com/libvips" } }, - "node_modules/@img/sharp-linux-arm": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", - "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", - "cpu": [ - "arm" - ], - "ideallyInert": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.0.5" - } - }, - "node_modules/@img/sharp-linux-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", - "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", - "cpu": [ - "arm64" - ], - "ideallyInert": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.0.4" - } - }, - "node_modules/@img/sharp-linux-s390x": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", - "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", - "cpu": [ - "s390x" - ], - "ideallyInert": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.0.4" - } - }, "node_modules/@img/sharp-linux-x64": { "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", - "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", "cpu": [ "x64" ], @@ -471,33 +243,8 @@ "@img/sharp-libvips-linux-x64": "1.0.4" } }, - "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", - "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", - "cpu": [ - "arm64" - ], - "ideallyInert": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" - } - }, "node_modules/@img/sharp-linuxmusl-x64": { "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", - "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", "cpu": [ "x64" ], @@ -516,70 +263,14 @@ "@img/sharp-libvips-linuxmusl-x64": "1.0.4" } }, - "node_modules/@img/sharp-wasm32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", - "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", - "cpu": [ - "wasm32" - ], - "ideallyInert": true, - "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", - "optional": true, - "dependencies": { - "@emnapi/runtime": "^1.2.0" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-ia32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", - "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", - "cpu": [ - "ia32" - ], - "ideallyInert": true, - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", - "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", - "cpu": [ - "x64" - ], - "ideallyInert": true, - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "dev": true, + "license": "MIT" }, "node_modules/@mapbox/node-pre-gyp": { "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", - "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "license": "BSD-3-Clause", "dependencies": { "detect-libc": "^2.0.0", "https-proxy-agent": "^5.0.0", @@ -615,11 +306,58 @@ } } }, + "node_modules/@napi-rs/canvas": { + "version": "0.1.82", + "license": "MIT", + "optional": true, + "workspaces": [ + "e2e/*" + ], + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@napi-rs/canvas-android-arm64": "0.1.82", + "@napi-rs/canvas-darwin-arm64": "0.1.82", + "@napi-rs/canvas-darwin-x64": "0.1.82", + "@napi-rs/canvas-linux-arm-gnueabihf": "0.1.82", + "@napi-rs/canvas-linux-arm64-gnu": "0.1.82", + "@napi-rs/canvas-linux-arm64-musl": "0.1.82", + "@napi-rs/canvas-linux-riscv64-gnu": "0.1.82", + "@napi-rs/canvas-linux-x64-gnu": "0.1.82", + "@napi-rs/canvas-linux-x64-musl": "0.1.82", + "@napi-rs/canvas-win32-x64-msvc": "0.1.82" + } + }, + "node_modules/@napi-rs/canvas-linux-x64-gnu": { + "version": "0.1.82", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@noble/hashes": { + "version": "1.8.0", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "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", "peer": true, "dependencies": { "@nodelib/fs.stat": "2.0.5", @@ -631,9 +369,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", "peer": true, "engines": { "node": ">= 8" @@ -641,9 +378,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", "peer": true, "dependencies": { "@nodelib/fs.scandir": "2.1.5", @@ -653,41 +389,208 @@ "node": ">= 8" } }, + "node_modules/@npmcli/fs": { + "version": "1.1.1", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "node_modules/@npmcli/move-file": { + "version": "1.1.2", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@paralleldrive/cuid2": { + "version": "2.3.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/hashes": "^1.1.5" + } + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.53.2", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@types/chai": { + "version": "5.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, "node_modules/@types/debug": { "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "license": "MIT", "dependencies": { "@types/ms": "*" } }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "dev": true, + "license": "MIT" + }, "node_modules/@types/ms": { "version": "0.7.34", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", - "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" + "license": "MIT" }, "node_modules/@types/node": { - "version": "20.14.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.12.tgz", - "integrity": "sha512-r7wNXakLeSsGT0H1AU863vS2wa5wBOK4bWMjZz2wj+8nBx+m5PeIn0k8AloSLpRuiwdRQZwarZqHE4FNArPuJQ==", + "version": "24.10.0", + "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~7.16.0" } }, "node_modules/@types/validator": { "version": "13.12.0", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.12.0.tgz", - "integrity": "sha512-nH45Lk7oPIJ1RVOF6JgFI6Dy0QpHEzq4QecZhvguxYPDwT8c93prCMqAtiIttm39voZ+DDR+qkNnMpJmMBRqag==" + "license": "MIT" + }, + "node_modules/@vitest/expect": { + "version": "4.0.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.0.8", + "@vitest/utils": "4.0.8", + "chai": "^6.2.0", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "4.0.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "4.0.8", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.0.8", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "4.0.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.0.8", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "4.0.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.0.8", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "4.0.8", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.0.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.0.8", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } }, "node_modules/abbrev": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + "license": "ISC" }, "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==", + "license": "MIT", "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" @@ -697,10 +600,9 @@ } }, "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.15.0", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -710,17 +612,15 @@ }, "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/agent-base": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", "dependencies": { "debug": "4" }, @@ -730,8 +630,7 @@ }, "node_modules/agent-base/node_modules/debug": { "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -746,14 +645,37 @@ }, "node_modules/agent-base/node_modules/ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "license": "MIT" + }, + "node_modules/agentkeepalive": { + "version": "4.6.0", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } }, "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", "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", @@ -768,17 +690,15 @@ }, "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==", + "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", "peer": true, "dependencies": { "color-convert": "^2.0.1" @@ -792,9 +712,8 @@ }, "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" @@ -805,20 +724,15 @@ }, "node_modules/append-field": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", - "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==", "license": "MIT" }, "node_modules/aproba": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + "license": "ISC" }, "node_modules/are-we-there-yet": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "deprecated": "This package is no longer supported.", + "license": "ISC", "dependencies": { "delegates": "^1.0.0", "readable-stream": "^3.6.0" @@ -829,34 +743,40 @@ }, "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", "peer": true }, "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==" + "license": "MIT" + }, + "node_modules/asap": { + "version": "2.0.6", + "dev": true, + "license": "MIT" + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } }, "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/aws-ssl-profiles": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.1.tgz", - "integrity": "sha512-+H+kuK34PfMaI9PNU/NSjBKL5hh/KDM9J72kwYeYEm0A8B1AC4fuCy3qsjnA7lxklgyXsB68yn8Z2xoZEjgwCQ==", + "license": "MIT", "engines": { "node": ">= 6.0.0" } }, "node_modules/axios": { "version": "1.12.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz", - "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -866,14 +786,31 @@ }, "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==" + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "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/bcrypt": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", - "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", "hasInstallScript": true, + "license": "MIT", "dependencies": { "@mapbox/node-pre-gyp": "^1.0.11", "node-addon-api": "^5.0.0" @@ -884,9 +821,8 @@ }, "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" }, @@ -894,10 +830,26 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/bindings": { + "version": "1.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, "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==", "license": "MIT", "dependencies": { "bytes": "3.1.2", @@ -920,8 +872,7 @@ }, "node_modules/body-parser/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==", + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -931,8 +882,6 @@ }, "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==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -941,9 +890,8 @@ }, "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" }, @@ -951,21 +899,39 @@ "node": ">=8" } }, + "node_modules/buffer": { + "version": "5.7.1", + "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-equal-constant-time": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + "license": "BSD-3-Clause" }, "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==", "license": "MIT" }, "node_modules/busboy": { "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", "dependencies": { "streamsearch": "^1.1.0" }, @@ -975,17 +941,66 @@ }, "node_modules/bytes": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "license": "MIT", "engines": { "node": ">= 0.8" } }, + "node_modules/cacache": { + "version": "15.3.0", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cacache/node_modules/lru-cache": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cacache/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/call-bind": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", @@ -1003,8 +1018,6 @@ }, "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", @@ -1016,19 +1029,25 @@ }, "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", "peer": true, "engines": { "node": ">=6" } }, + "node_modules/chai": { + "version": "6.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "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", "peer": true, "dependencies": { "ansi-styles": "^4.1.0", @@ -1043,9 +1062,8 @@ }, "node_modules/chalk/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", "peer": true, "engines": { "node": ">=8" @@ -1053,9 +1071,8 @@ }, "node_modules/chalk/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", "peer": true, "dependencies": { "has-flag": "^4.0.0" @@ -1066,9 +1083,8 @@ }, "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", @@ -1090,16 +1106,22 @@ }, "node_modules/chownr": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "license": "ISC", "engines": { "node": ">=10" } }, + "node_modules/clean-stack": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, "node_modules/color": { "version": "4.2.3", - "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", - "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", "license": "MIT", "dependencies": { "color-convert": "^2.0.1", @@ -1111,8 +1133,7 @@ }, "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==", + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -1122,13 +1143,10 @@ }, "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==" + "license": "MIT" }, "node_modules/color-string": { "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", - "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", "license": "MIT", "dependencies": { "color-name": "^1.0.0", @@ -1137,16 +1155,13 @@ }, "node_modules/color-support": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "license": "ISC", "bin": { "color-support": "bin.js" } }, "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" @@ -1155,15 +1170,20 @@ "node": ">= 0.8" } }, + "node_modules/component-emitter": { + "version": "1.3.1", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/concat-map": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + "license": "MIT" }, "node_modules/concat-stream": { "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "engines": [ "node >= 0.8" ], @@ -1177,8 +1197,6 @@ }, "node_modules/concat-stream/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", @@ -1192,14 +1210,10 @@ }, "node_modules/concat-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/concat-stream/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" @@ -1207,13 +1221,11 @@ }, "node_modules/console-control-strings": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + "license": "ISC" }, "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==", + "license": "MIT", "dependencies": { "safe-buffer": "5.2.1" }, @@ -1223,8 +1235,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==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -1232,8 +1242,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==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -1241,19 +1249,20 @@ }, "node_modules/cookie-signature": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + "license": "MIT" + }, + "node_modules/cookiejar": { + "version": "2.1.4", + "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==", "license": "MIT" }, "node_modules/cors": { "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", "dependencies": { "object-assign": "^4", "vary": "^1" @@ -1262,13 +1271,27 @@ "node": ">= 0.10" } }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "node_modules/cross-env": { + "version": "7.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -1280,14 +1303,11 @@ }, "node_modules/crypto": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz", - "integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==", - "deprecated": "This package is no longer supported. It's now a built-in Node module. If you've depended on crypto, you should switch to the one that's built-in." + "license": "ISC" }, "node_modules/csv-parser": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/csv-parser/-/csv-parser-3.0.0.tgz", - "integrity": "sha512-s6OYSXAK3IdKqYO33y09jhypG/bSDHPuyCme/IdEHfWpLf/jKcpitVFyOC6UemgGk8v7Q5u2XE0vvwmanxhGlQ==", + "license": "MIT", "dependencies": { "minimist": "^1.2.0" }, @@ -1298,19 +1318,8 @@ "node": ">= 10" } }, - "node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, "node_modules/date-fns": { "version": "2.30.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", - "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.21.0" @@ -1325,23 +1334,27 @@ }, "node_modules/debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } }, + "node_modules/deep-extend": { + "version": "0.6.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, "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", "peer": true }, "node_modules/define-data-property": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", @@ -1357,8 +1370,6 @@ }, "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" @@ -1366,21 +1377,17 @@ }, "node_modules/delegates": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + "license": "MIT" }, "node_modules/denque": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "license": "Apache-2.0", "engines": { "node": ">=0.10" } }, "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==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -1388,8 +1395,6 @@ }, "node_modules/destroy": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", "license": "MIT", "engines": { "node": ">= 0.8", @@ -1398,16 +1403,23 @@ }, "node_modules/detect-libc": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", - "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "license": "Apache-2.0", "engines": { "node": ">=8" } }, + "node_modules/dezalgo": { + "version": "1.0.4", + "dev": true, + "license": "ISC", + "dependencies": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, "node_modules/dotenv": { "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "license": "BSD-2-Clause", "engines": { "node": ">=12" }, @@ -1417,13 +1429,10 @@ }, "node_modules/dottie": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.6.tgz", - "integrity": "sha512-iGCHkfUc5kFekGiqhe8B/mdaurD+lakO9txNnTvKtA6PISrw86LgqHvRzWYPyoE2Ph5aMIrCw9/uko6XHTKCwA==" + "license": "MIT" }, "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", @@ -1436,34 +1445,59 @@ }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", "dependencies": { "safe-buffer": "^5.0.1" } }, "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==" + "license": "MIT" }, "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==" + "license": "MIT" }, "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==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, + "node_modules/encoding": { + "version": "0.1.13", + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "dev": true, + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "dev": true, + "license": "MIT", + "optional": true + }, "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" @@ -1471,17 +1505,18 @@ }, "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-module-lexer": { + "version": "1.7.0", + "dev": true, + "license": "MIT" + }, "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" @@ -1492,8 +1527,6 @@ }, "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", @@ -1505,16 +1538,54 @@ "node": ">= 0.4" } }, + "node_modules/esbuild": { + "version": "0.25.12", + "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/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==" + "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", "peer": true, "engines": { "node": ">=10" @@ -1525,9 +1596,8 @@ }, "node_modules/eslint": { "version": "9.9.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.9.0.tgz", - "integrity": "sha512-JfiKJrbx0506OEerjK2Y1QlldtBxkAlLxT5OEcRF8uaQ86noDe2k31Vw9rnSWv+MXZHj7OOUV/dA0AhdLFcyvA==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", @@ -1585,9 +1655,8 @@ }, "node_modules/eslint-scope": { "version": "8.0.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", - "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", "dev": true, + "license": "BSD-2-Clause", "peer": true, "dependencies": { "esrecurse": "^4.3.0", @@ -1602,9 +1671,8 @@ }, "node_modules/eslint-visitor-keys": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", "dev": true, + "license": "Apache-2.0", "peer": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1615,9 +1683,8 @@ }, "node_modules/eslint/node_modules/debug": { "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "ms": "2.1.2" @@ -1633,9 +1700,8 @@ }, "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", "peer": true, "dependencies": { "is-glob": "^4.0.3" @@ -1646,16 +1712,14 @@ }, "node_modules/eslint/node_modules/ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/espree": { "version": "10.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", - "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", "dev": true, + "license": "BSD-2-Clause", "peer": true, "dependencies": { "acorn": "^8.12.0", @@ -1671,9 +1735,8 @@ }, "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" }, @@ -1683,9 +1746,8 @@ }, "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" }, @@ -1695,18 +1757,24 @@ }, "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": "3.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, "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", "peer": true, "engines": { "node": ">=0.10.0" @@ -1714,17 +1782,29 @@ }, "node_modules/etag": { "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "license": "MIT", "engines": { "node": ">= 0.6" } }, + "node_modules/expand-template": { + "version": "2.0.3", + "dev": true, + "license": "(MIT OR WTFPL)", + "engines": { + "node": ">=6" + } + }, + "node_modules/expect-type": { + "version": "1.2.2", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/express": { "version": "4.21.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", - "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", "license": "MIT", "dependencies": { "accepts": "~1.3.8", @@ -1769,8 +1849,6 @@ }, "node_modules/express/node_modules/encodeurl": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -1778,63 +1856,40 @@ }, "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", "peer": true }, "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", "peer": true }, "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", "peer": true }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "dev": true, + "license": "MIT" + }, "node_modules/fastq": { "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, + "license": "ISC", "peer": true, "dependencies": { "reusify": "^1.0.4" } }, - "node_modules/fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "paypal", - "url": "https://paypal.me/jimmywarting" - } - ], - "license": "MIT", - "dependencies": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - }, - "engines": { - "node": "^12.20 || >= 14.13" - } - }, "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", "peer": true, "dependencies": { "flat-cache": "^4.0.0" @@ -1843,11 +1898,15 @@ "node": ">=16.0.0" } }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, "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" }, @@ -1857,8 +1916,7 @@ }, "node_modules/finalhandler": { "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", "dependencies": { "debug": "2.6.9", "encodeurl": "~2.0.0", @@ -1874,17 +1932,15 @@ }, "node_modules/finalhandler/node_modules/encodeurl": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "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", "peer": true, "dependencies": { "locate-path": "^6.0.0", @@ -1899,9 +1955,8 @@ }, "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", "peer": true, "dependencies": { "flatted": "^3.2.9", @@ -1913,15 +1968,12 @@ }, "node_modules/flatted": { "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true, + "license": "ISC", "peer": true }, "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", @@ -1940,8 +1992,6 @@ }, "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", @@ -1954,39 +2004,44 @@ "node": ">= 6" } }, - "node_modules/formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "node_modules/formidable": { + "version": "3.5.4", + "dev": true, "license": "MIT", "dependencies": { - "fetch-blob": "^3.1.2" + "@paralleldrive/cuid2": "^2.2.2", + "dezalgo": "^1.0.4", + "once": "^1.4.0" }, "engines": { - "node": ">=12.20.0" + "node": ">=14.0.0" + }, + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" } }, "node_modules/forwarded": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/fresh": { "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "license": "MIT", "engines": { "node": ">= 0.6" } }, + "node_modules/fs-constants": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, "node_modules/fs-minipass": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "license": "ISC", "dependencies": { "minipass": "^3.0.0" }, @@ -1996,8 +2051,7 @@ }, "node_modules/fs-minipass/node_modules/minipass": { "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -2007,28 +2061,10 @@ }, "node_modules/fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "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, - "ideallyInert": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } + "license": "ISC" }, "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" @@ -2036,9 +2072,7 @@ }, "node_modules/gauge": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "deprecated": "This package is no longer supported.", + "license": "ISC", "dependencies": { "aproba": "^1.0.3 || ^2.0.0", "color-support": "^1.1.2", @@ -2056,16 +2090,13 @@ }, "node_modules/generate-function": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", - "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "license": "MIT", "dependencies": { "is-property": "^1.0.2" } }, "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", @@ -2088,8 +2119,6 @@ }, "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", @@ -2099,11 +2128,14 @@ "node": ">= 0.4" } }, + "node_modules/github-from-package": { + "version": "0.0.0", + "dev": true, + "license": "MIT" + }, "node_modules/glob": { "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -2121,9 +2153,8 @@ }, "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" }, @@ -2133,9 +2164,8 @@ }, "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", "peer": true, "engines": { "node": ">=18" @@ -2146,8 +2176,6 @@ }, "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" @@ -2156,19 +2184,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "dev": true, + "license": "ISC", + "optional": true + }, "node_modules/has-flag": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/has-property-descriptors": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "license": "MIT", "dependencies": { "es-define-property": "^1.0.0" @@ -2179,8 +2210,6 @@ }, "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" @@ -2191,8 +2220,6 @@ }, "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" @@ -2206,13 +2233,10 @@ }, "node_modules/has-unicode": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + "license": "ISC" }, "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" @@ -2221,10 +2245,14 @@ "node": ">= 0.4" } }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "dev": true, + "license": "BSD-2-Clause", + "optional": true + }, "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==", "license": "MIT", "dependencies": { "depd": "2.0.0", @@ -2237,10 +2265,46 @@ "node": ">= 0.8" } }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-proxy-agent/node_modules/debug": { + "version": "4.4.3", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/http-proxy-agent/node_modules/ms": { + "version": "2.1.3", + "dev": true, + "license": "MIT", + "optional": true + }, "node_modules/https-proxy-agent": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", "dependencies": { "agent-base": "6", "debug": "4" @@ -2251,8 +2315,7 @@ }, "node_modules/https-proxy-agent/node_modules/debug": { "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -2267,13 +2330,20 @@ }, "node_modules/https-proxy-agent/node_modules/ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "license": "MIT" + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.0.0" + } }, "node_modules/iconv-lite": { "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -2281,11 +2351,29 @@ "node": ">=0.10.0" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "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", "peer": true, "engines": { "node": ">= 4" @@ -2293,15 +2381,13 @@ }, "node_modules/ignore-by-default": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/import-fresh": { "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "parent-module": "^1.0.0", @@ -2316,27 +2402,37 @@ }, "node_modules/imurmurhash": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, - "peer": true, + "license": "MIT", "engines": { "node": ">=0.8.19" } }, + "node_modules/indent-string": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "dev": true, + "license": "ISC", + "optional": true + }, "node_modules/inflection": { "version": "1.13.4", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz", - "integrity": "sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw==", "engines": [ "node >= 0.4.0" - ] + ], + "license": "MIT" }, "node_modules/inflight": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -2344,28 +2440,37 @@ }, "node_modules/inherits": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "dev": true, + "license": "ISC" + }, + "node_modules/ip-address": { + "version": "10.1.0", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 12" + } }, "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==", + "license": "MIT", "engines": { "node": ">= 0.10" } }, "node_modules/is-arrayish": { "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", "license": "MIT" }, "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" }, @@ -2375,26 +2480,23 @@ }, "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==", + "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" }, @@ -2402,20 +2504,24 @@ "node": ">=0.10.0" } }, + "node_modules/is-lambda": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "optional": true + }, "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-path-inside": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -2423,27 +2529,21 @@ }, "node_modules/is-property": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" + "license": "MIT" }, "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/isexe": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true, - "peer": true + "license": "ISC" }, "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", "peer": true, "dependencies": { "argparse": "^2.0.1" @@ -2454,29 +2554,25 @@ }, "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", "peer": true }, "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", "peer": true }, "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", "peer": true }, "node_modules/jsonwebtoken": { "version": "9.0.2", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", - "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "license": "MIT", "dependencies": { "jws": "^3.2.2", "lodash.includes": "^4.3.0", @@ -2496,13 +2592,11 @@ }, "node_modules/jsonwebtoken/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==" + "license": "MIT" }, "node_modules/jwa": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "license": "MIT", "dependencies": { "buffer-equal-constant-time": "1.0.1", "ecdsa-sig-formatter": "1.0.11", @@ -2511,8 +2605,7 @@ }, "node_modules/jws": { "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "license": "MIT", "dependencies": { "jwa": "^1.4.1", "safe-buffer": "^5.0.1" @@ -2520,9 +2613,8 @@ }, "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", "peer": true, "dependencies": { "json-buffer": "3.0.1" @@ -2530,9 +2622,8 @@ }, "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", "peer": true, "dependencies": { "prelude-ls": "^1.2.1", @@ -2544,9 +2635,8 @@ }, "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", "peer": true, "dependencies": { "p-locate": "^5.0.0" @@ -2560,68 +2650,64 @@ }, "node_modules/lodash": { "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "license": "MIT" }, "node_modules/lodash.includes": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + "license": "MIT" }, "node_modules/lodash.isboolean": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + "license": "MIT" }, "node_modules/lodash.isinteger": { "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + "license": "MIT" }, "node_modules/lodash.isnumber": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + "license": "MIT" }, "node_modules/lodash.isplainobject": { "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + "license": "MIT" }, "node_modules/lodash.isstring": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + "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", "peer": true }, "node_modules/lodash.once": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + "license": "MIT" }, "node_modules/long": { "version": "5.2.3", - "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", - "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + "license": "Apache-2.0" }, "node_modules/lru-cache": { "version": "8.0.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz", - "integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==", + "license": "ISC", "engines": { "node": ">=16.14" } }, + "node_modules/magic-string": { + "version": "0.30.21", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, "node_modules/make-dir": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "license": "MIT", "dependencies": { "semver": "^6.0.0" }, @@ -2634,16 +2720,64 @@ }, "node_modules/make-dir/node_modules/semver": { "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, + "node_modules/make-fetch-happen": { + "version": "9.1.0", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/make-fetch-happen/node_modules/lru-cache": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-fetch-happen/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "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" @@ -2651,8 +2785,6 @@ }, "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==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -2660,8 +2792,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==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2669,16 +2799,13 @@ }, "node_modules/methods": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/mime": { "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "license": "MIT", "bin": { "mime": "cli.js" @@ -2689,16 +2816,14 @@ }, "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/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" }, @@ -2708,8 +2833,7 @@ }, "node_modules/minimatch": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -2719,8 +2843,6 @@ }, "node_modules/minimist": { "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2728,16 +2850,139 @@ }, "node_modules/minipass": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-collect/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-fetch": { + "version": "1.4.1", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "optionalDependencies": { + "encoding": "^0.1.12" + } + }, + "node_modules/minipass-fetch/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, "engines": { "node": ">=8" } }, "node_modules/minizlib": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "license": "MIT", "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" @@ -2748,8 +2993,7 @@ }, "node_modules/minizlib/node_modules/minipass": { "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -2759,8 +3003,7 @@ }, "node_modules/mkdirp": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", "bin": { "mkdirp": "bin/cmd.js" }, @@ -2768,18 +3011,21 @@ "node": ">=10" } }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "dev": true, + "license": "MIT" + }, "node_modules/moment": { "version": "2.30.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", - "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "license": "MIT", "engines": { "node": "*" } }, "node_modules/moment-timezone": { "version": "0.5.45", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.45.tgz", - "integrity": "sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ==", + "license": "MIT", "dependencies": { "moment": "^2.29.4" }, @@ -2789,13 +3035,10 @@ }, "node_modules/ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "license": "MIT" }, "node_modules/multer": { "version": "1.4.5-lts.1", - "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", - "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", "license": "MIT", "dependencies": { "append-field": "^1.0.0", @@ -2812,8 +3055,6 @@ }, "node_modules/multer/node_modules/mkdirp": { "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "license": "MIT", "dependencies": { "minimist": "^1.2.6" @@ -2824,8 +3065,7 @@ }, "node_modules/mysql2": { "version": "3.10.3", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.10.3.tgz", - "integrity": "sha512-k43gmH9i79rZD4hGPdj7pDuT0UBiFjs4UzXEy1cJrV0QqcSABomoLwvejqdbcXN+Vd7gi999CVM6o9vCPKq29g==", + "license": "MIT", "dependencies": { "aws-ssl-profiles": "^1.1.1", "denque": "^2.1.0", @@ -2843,8 +3083,7 @@ }, "node_modules/named-placeholders": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", - "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", + "license": "MIT", "dependencies": { "lru-cache": "^7.14.1" }, @@ -2854,89 +3093,154 @@ }, "node_modules/named-placeholders/node_modules/lru-cache": { "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "license": "ISC", "engines": { "node": ">=12" } }, + "node_modules/nanoid": { + "version": "3.3.11", + "dev": true, + "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/napi-build-utils": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, "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", "peer": true }, "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==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, + "node_modules/node-abi": { + "version": "3.80.0", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/node-addon-api": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", - "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + "license": "MIT" }, - "node_modules/node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "deprecated": "Use your platform's native DOMException instead", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "github", - "url": "https://paypal.me/jimmywarting" - } - ], - "license": "MIT", + "node_modules/node-cron": { + "version": "4.2.1", + "license": "ISC", "engines": { - "node": ">=10.5.0" + "node": ">=6.0.0" } }, "node_modules/node-ensure": { "version": "0.0.0", - "resolved": "https://registry.npmjs.org/node-ensure/-/node-ensure-0.0.0.tgz", - "integrity": "sha512-DRI60hzo2oKN1ma0ckc6nQWlHU69RH6xN0sjQTjMpChPfTYvKZdcQFfdYK2RWbJcKyUizSIy/l8OTGxMAM1QDw==", "license": "MIT" }, - "node_modules/node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "node_modules/node-gyp": { + "version": "8.4.1", + "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^9.1.0", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">= 10.12.0" + } + }, + "node_modules/node-gyp/node_modules/are-we-there-yet": { + "version": "3.0.1", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-gyp/node_modules/gauge": { + "version": "4.0.4", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-gyp/node_modules/npmlog": { + "version": "6.0.2", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/nodemailer": { - "version": "6.9.14", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.14.tgz", - "integrity": "sha512-Dobp/ebDKBvz91sbtRKhcznLThrKxKt97GI2FAlAyy+fk19j73Uz3sBXolVtmcXjaorivqsbbbjDY+Jkt4/bQA==", + "version": "7.0.9", + "license": "MIT-0", "engines": { "node": ">=6.0.0" } }, "node_modules/nodemon": { "version": "3.1.4", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.4.tgz", - "integrity": "sha512-wjPBbFhtpJwmIeY2yP7QF+UKzPfltVGtfce1g/bB15/8vCGZj8uxD62b/b9M9/WVgme0NZudpownKN+c0plXlQ==", "dev": true, + "license": "MIT", "dependencies": { "chokidar": "^3.5.2", "debug": "^4", @@ -2962,9 +3266,8 @@ }, "node_modules/nodemon/node_modules/debug": { "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -2979,14 +3282,12 @@ }, "node_modules/nodemon/node_modules/ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/nopt": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "license": "ISC", "dependencies": { "abbrev": "1" }, @@ -2999,18 +3300,15 @@ }, "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/npmlog": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "deprecated": "This package is no longer supported.", + "license": "ISC", "dependencies": { "are-we-there-yet": "^2.0.0", "console-control-strings": "^1.1.0", @@ -3020,16 +3318,13 @@ }, "node_modules/object-assign": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/object-inspect": { "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -3040,8 +3335,7 @@ }, "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==", + "license": "MIT", "dependencies": { "ee-first": "1.1.1" }, @@ -3051,17 +3345,15 @@ }, "node_modules/once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", "dependencies": { "wrappy": "1" } }, "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", "peer": true, "dependencies": { "deep-is": "^0.1.3", @@ -3077,9 +3369,8 @@ }, "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", "peer": true, "dependencies": { "yocto-queue": "^0.1.0" @@ -3093,9 +3384,8 @@ }, "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", "peer": true, "dependencies": { "p-limit": "^3.0.2" @@ -3107,11 +3397,25 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-map": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "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", "peer": true, "dependencies": { "callsites": "^3.0.0" @@ -3122,17 +3426,15 @@ }, "node_modules/parseurl": { "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "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", "peer": true, "engines": { "node": ">=8" @@ -3140,32 +3442,30 @@ }, "node_modules/path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "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, - "peer": true, + "license": "MIT", "engines": { "node": ">=8" } }, "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==", + "license": "MIT" + }, + "node_modules/pathe": { + "version": "2.0.3", + "dev": true, "license": "MIT" }, "node_modules/pdf-parse": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pdf-parse/-/pdf-parse-1.1.1.tgz", - "integrity": "sha512-v6ZJ/efsBpGrGGknjtq9J/oC8tZWq0KWL5vQrk2GlzLEQPUDB1ex+13Rmidl1neNN358Jn9EHZw5y07FFtaC7A==", "license": "MIT", "dependencies": { "debug": "^3.1.0", @@ -3177,8 +3477,6 @@ }, "node_modules/pdf-parse/node_modules/debug": { "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "license": "MIT", "dependencies": { "ms": "^2.1.1" @@ -3186,20 +3484,31 @@ }, "node_modules/pdf-parse/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==", "license": "MIT" }, + "node_modules/pdfjs-dist": { + "version": "5.4.394", + "license": "Apache-2.0", + "engines": { + "node": ">=20.16.0 || >=22.3.0" + }, + "optionalDependencies": { + "@napi-rs/canvas": "^0.1.81" + } + }, "node_modules/pg-connection-string": { "version": "2.6.4", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.4.tgz", - "integrity": "sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA==" + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "dev": true, + "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" }, @@ -3207,119 +3516,85 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/playwright": { - "version": "1.55.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.55.1.tgz", - "integrity": "sha512-cJW4Xd/G3v5ovXtJJ52MAOclqeac9S/aGGgRzLabuF8TnIb6xHvMzKIa6JmrRzUkeXJgfL1MhukP0NK6l39h3A==", - "license": "Apache-2.0", - "dependencies": { - "playwright-core": "1.55.1" - }, - "bin": { - "playwright": "cli.js" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "fsevents": "2.3.2" - } - }, - "node_modules/playwright-core": { - "version": "1.55.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.55.1.tgz", - "integrity": "sha512-Z6Mh9mkwX+zxSlHqdr5AOcJnfp+xUWLCt9uKV18fhzA8eyxUd8NUWzAjxUh55RZKSYwDGX0cfaySdhZJGMoJ+w==", - "license": "Apache-2.0", - "bin": { - "playwright-core": "cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/playwright/node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "hasInstallScript": true, - "ideallyInert": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" + "node_modules/postcss": { + "version": "8.5.6", + "dev": true, + "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" + } ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "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, - "peer": true, - "engines": { - "node": ">= 0.8.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==", - "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==", + "license": "MIT", "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, "engines": { - "node": ">= 0.10" + "node": "^10 || ^12 || >=14" } }, - "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/pstree.remy": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", - "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", - "dev": true - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "node_modules/prebuild-install": { + "version": "7.1.3", "dev": true, - "peer": true, - "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==", + "license": "MIT", "dependencies": { - "side-channel": "^1.0.6" + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" }, "engines": { - "node": ">=0.6" + "node": ">=10" + } + }, + "node_modules/prebuild-install/node_modules/decompress-response": { + "version": "6.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "node_modules/prebuild-install/node_modules/mimic-response": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/prebuild-install/node_modules/simple-get": { + "version": "4.0.1", "dev": true, "funding": [ { @@ -3335,12 +3610,118 @@ "url": "https://feross.org/support" } ], + "license": "MIT", + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "license": "MIT" + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "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", + "license": "MIT" + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "dev": true, + "license": "MIT" + }, + "node_modules/pump": { + "version": "3.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.13.0", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "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", "peer": true }, "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==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -3348,8 +3729,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==", "license": "MIT", "dependencies": { "bytes": "3.1.2", @@ -3363,8 +3742,7 @@ }, "node_modules/raw-body/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==", + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -3372,10 +3750,31 @@ "node": ">=0.10.0" } }, + "node_modules/rc": { + "version": "1.2.8", + "dev": true, + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "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==", + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -3387,9 +3786,8 @@ }, "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" }, @@ -3399,24 +3797,30 @@ }, "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", "peer": true, "engines": { "node": ">=4" } }, + "node_modules/retry": { + "version": "0.12.0", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 4" + } + }, "node_modules/retry-as-promised": { "version": "7.0.4", - "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-7.0.4.tgz", - "integrity": "sha512-XgmCoxKWkDofwH8WddD0w85ZfqYz+ZHlr5yo+3YUCfycWawU56T5ckWXsScsj5B8tqUcIG67DxXByo3VUgiAdA==" + "license": "MIT" }, "node_modules/reusify": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, + "license": "MIT", "peer": true, "engines": { "iojs": ">=1.0.0", @@ -3425,9 +3829,7 @@ }, "node_modules/rimraf": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -3438,10 +3840,48 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rollup": { + "version": "4.53.2", + "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/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": [ { @@ -3457,6 +3897,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "peer": true, "dependencies": { "queue-microtask": "^1.2.2" @@ -3464,8 +3905,6 @@ }, "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==", "funding": [ { "type": "github", @@ -3479,17 +3918,16 @@ "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==" + "license": "MIT" }, "node_modules/semver": { "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -3499,8 +3937,6 @@ }, "node_modules/send": { "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "license": "MIT", "dependencies": { "debug": "2.6.9", @@ -3523,25 +3959,20 @@ }, "node_modules/send/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==", "license": "MIT" }, "node_modules/seq-queue": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", - "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" + "version": "0.0.5" }, "node_modules/sequelize": { "version": "6.37.3", - "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.37.3.tgz", - "integrity": "sha512-V2FTqYpdZjPy3VQrZvjTPnOoLm0KudCRXfGWp48QwhyPPp2yW8z0p0sCYZd/em847Tl2dVxJJ1DR+hF+O77T7A==", "funding": [ { "type": "opencollective", "url": "https://opencollective.com/sequelize" } ], + "license": "MIT", "dependencies": { "@types/debug": "^4.1.8", "@types/validator": "^13.7.17", @@ -3595,16 +4026,14 @@ }, "node_modules/sequelize-pool": { "version": "7.1.0", - "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-7.1.0.tgz", - "integrity": "sha512-G9c0qlIWQSK29pR/5U2JF5dDQeqqHRragoyahj/Nx4KOOQ3CPPfzxnfqFPCSB7x5UgjOgnZ61nSxz+fjDpRlJg==", + "license": "MIT", "engines": { "node": ">= 10.0.0" } }, "node_modules/sequelize/node_modules/debug": { "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -3619,13 +4048,11 @@ }, "node_modules/sequelize/node_modules/ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "license": "MIT" }, "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==", + "license": "MIT", "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", @@ -3638,21 +4065,17 @@ }, "node_modules/serve-static/node_modules/encodeurl": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/set-blocking": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + "license": "ISC" }, "node_modules/set-function-length": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", @@ -3668,14 +4091,10 @@ }, "node_modules/setprototypeof": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "license": "ISC" }, "node_modules/sharp": { "version": "0.33.5", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", - "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { @@ -3713,10 +4132,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, - "peer": true, + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -3726,18 +4143,14 @@ }, "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, - "peer": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/side-channel": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "license": "MIT", "dependencies": { "call-bind": "^1.0.7", @@ -3752,15 +4165,38 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "dev": true, + "license": "ISC" + }, "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==" + "license": "ISC" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "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/simple-swizzle": { "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", "license": "MIT", "dependencies": { "is-arrayish": "^0.3.1" @@ -3768,9 +4204,8 @@ }, "node_modules/simple-update-notifier": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", - "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", "dev": true, + "license": "MIT", "dependencies": { "semver": "^7.5.3" }, @@ -3778,42 +4213,167 @@ "node": ">=10" } }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.7", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "ip-address": "^10.0.1", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "6.2.1", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/socks-proxy-agent/node_modules/debug": { + "version": "4.4.3", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socks-proxy-agent/node_modules/ms": { + "version": "2.1.3", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sqlite3": { + "version": "5.1.7", + "dev": true, + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "bindings": "^1.5.0", + "node-addon-api": "^7.0.0", + "prebuild-install": "^7.1.1", + "tar": "^6.1.11" + }, + "optionalDependencies": { + "node-gyp": "8.x" + }, + "peerDependencies": { + "node-gyp": "8.x" + }, + "peerDependenciesMeta": { + "node-gyp": { + "optional": true + } + } + }, + "node_modules/sqlite3/node_modules/node-addon-api": { + "version": "7.1.1", + "dev": true, + "license": "MIT" + }, "node_modules/sqlstring": { "version": "2.3.3", - "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", - "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, + "node_modules/ssri": { + "version": "8.0.1", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/ssri/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "dev": true, + "license": "MIT" + }, "node_modules/statuses": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, + "node_modules/std-env": { + "version": "3.10.0", + "dev": true, + "license": "MIT" + }, "node_modules/streamsearch": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", "engines": { "node": ">=10.0.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==", + "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==", + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -3825,8 +4385,7 @@ }, "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==", + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -3836,9 +4395,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", "peer": true, "engines": { "node": ">=8" @@ -3847,11 +4405,73 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/superagent": { + "version": "10.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "component-emitter": "^1.3.1", + "cookiejar": "^2.1.4", + "debug": "^4.3.7", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.4", + "formidable": "^3.5.4", + "methods": "^1.1.2", + "mime": "2.6.0", + "qs": "^6.11.2" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/superagent/node_modules/debug": { + "version": "4.4.3", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/superagent/node_modules/mime": { + "version": "2.6.0", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/superagent/node_modules/ms": { + "version": "2.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/supertest": { + "version": "7.1.4", + "dev": true, + "license": "MIT", + "dependencies": { + "methods": "^1.1.2", + "superagent": "^10.2.3" + }, + "engines": { + "node": ">=14.18.0" + } + }, "node_modules/supports-color": { "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^3.0.0" }, @@ -3861,8 +4481,7 @@ }, "node_modules/tar": { "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "license": "ISC", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -3875,18 +4494,107 @@ "node": ">=10" } }, + "node_modules/tar-fs": { + "version": "2.1.4", + "dev": true, + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "dev": true, + "license": "ISC" + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/text-table": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true, + "license": "MIT", "peer": true }, + "node_modules/tinybench": { + "version": "2.9.0", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "0.3.2", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "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", + "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", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/tinyrainbow": { + "version": "3.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "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" }, @@ -3896,8 +4604,6 @@ }, "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==", "license": "MIT", "engines": { "node": ">=0.6" @@ -3905,37 +4611,35 @@ }, "node_modules/toposort-class": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", - "integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==" + "license": "MIT" }, "node_modules/touch": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", - "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", "dev": true, + "license": "ISC", "bin": { "nodetouch": "bin/nodetouch.js" } }, "node_modules/tr46": { "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "license": "MIT" }, - "node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", - "ideallyInert": true, - "license": "0BSD", - "optional": true + "node_modules/tunnel-agent": { + "version": "0.6.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } }, "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", "peer": true, "dependencies": { "prelude-ls": "^1.2.1" @@ -3946,8 +4650,6 @@ }, "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==", "license": "MIT", "dependencies": { "media-typer": "0.3.0", @@ -3959,34 +4661,46 @@ }, "node_modules/typedarray": { "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", "license": "MIT" }, "node_modules/undefsafe": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", - "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + "version": "7.16.0", + "license": "MIT" + }, + "node_modules/unique-filename": { + "version": "1.1.1", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/unique-slug": { + "version": "2.0.2", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "imurmurhash": "^0.1.4" + } }, "node_modules/unpipe": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "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", "peer": true, "dependencies": { "punycode": "^2.1.0" @@ -3994,46 +4708,248 @@ }, "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==" + "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==", + "license": "MIT", "engines": { "node": ">= 0.4.0" } }, "node_modules/uuid": { "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } }, "node_modules/validator": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", - "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", + "version": "13.15.23", + "license": "MIT", "engines": { "node": ">= 0.10" } }, "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==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, + "node_modules/vite": { + "version": "7.2.2", + "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/node_modules/fdir": { + "version": "6.5.0", + "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", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vitest": { + "version": "4.0.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "4.0.8", + "@vitest/mocker": "4.0.8", + "@vitest/pretty-format": "4.0.8", + "@vitest/runner": "4.0.8", + "@vitest/snapshot": "4.0.8", + "@vitest/spy": "4.0.8", + "@vitest/utils": "4.0.8", + "debug": "^4.4.3", + "es-module-lexer": "^1.7.0", + "expect-type": "^1.2.2", + "magic-string": "^0.30.21", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^3.10.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.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": "^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": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.0.8", + "@vitest/browser-preview": "4.0.8", + "@vitest/browser-webdriverio": "4.0.8", + "@vitest/ui": "4.0.8", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/debug": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/vitest/node_modules/debug": { + "version": "4.4.3", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/vitest/node_modules/ms": { + "version": "2.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/vitest/node_modules/picomatch": { + "version": "4.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/vue-eslint-parser": { "version": "9.4.3", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz", - "integrity": "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^4.3.4", "eslint-scope": "^7.1.1", @@ -4055,9 +4971,8 @@ }, "node_modules/vue-eslint-parser/node_modules/debug": { "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -4072,9 +4987,8 @@ }, "node_modules/vue-eslint-parser/node_modules/eslint-scope": { "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -4088,9 +5002,8 @@ }, "node_modules/vue-eslint-parser/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" }, @@ -4100,9 +5013,8 @@ }, "node_modules/vue-eslint-parser/node_modules/espree": { "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", @@ -4117,29 +5029,15 @@ }, "node_modules/vue-eslint-parser/node_modules/ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/web-streams-polyfill": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", - "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", - "license": "MIT", - "engines": { - "node": ">= 8" - } + "dev": true, + "license": "MIT" }, "node_modules/webidl-conversions": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", "license": "BSD-2-Clause" }, "node_modules/whatwg-url": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "license": "MIT", "dependencies": { "tr46": "~0.0.3", @@ -4148,10 +5046,8 @@ }, "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, - "peer": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -4162,27 +5058,39 @@ "node": ">= 8" } }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/wide-align": { "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "license": "ISC", "dependencies": { "string-width": "^1.0.2 || 2 || 3 || 4" } }, "node_modules/wkx": { "version": "0.5.0", - "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", - "integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==", + "license": "MIT", "dependencies": { "@types/node": "*" } }, "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", "peer": true, "engines": { "node": ">=0.10.0" @@ -4190,13 +5098,10 @@ }, "node_modules/wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "license": "ISC" }, "node_modules/xtend": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "license": "MIT", "engines": { "node": ">=0.4" @@ -4204,14 +5109,12 @@ }, "node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "license": "ISC" }, "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", "peer": true, "engines": { "node": ">=10" diff --git a/backend/node_modules/@types/node/README.md b/backend/node_modules/@types/node/README.md index 7d75f1c..d221535 100644 --- a/backend/node_modules/@types/node/README.md +++ b/backend/node_modules/@types/node/README.md @@ -8,8 +8,8 @@ This package contains type definitions for node (https://nodejs.org/). Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node. ### Additional Details - * Last updated: Tue, 23 Jul 2024 18:09:25 GMT + * Last updated: Mon, 03 Nov 2025 01:29:59 GMT * Dependencies: [undici-types](https://npmjs.com/package/undici-types) # Credits -These definitions were written by [Microsoft TypeScript](https://github.com/Microsoft), [Alberto Schiabel](https://github.com/jkomyno), [Alvis HT Tang](https://github.com/alvis), [Andrew Makarov](https://github.com/r3nya), [Benjamin Toueg](https://github.com/btoueg), [Chigozirim C.](https://github.com/smac89), [David Junger](https://github.com/touffy), [Deividas Bakanas](https://github.com/DeividasBakanas), [Eugene Y. Q. Shen](https://github.com/eyqs), [Hannes Magnusson](https://github.com/Hannes-Magnusson-CK), [Huw](https://github.com/hoo29), [Kelvin Jin](https://github.com/kjin), [Klaus Meinhardt](https://github.com/ajafff), [Lishude](https://github.com/islishude), [Mariusz Wiktorczyk](https://github.com/mwiktorczyk), [Mohsen Azimi](https://github.com/mohsen1), [Nikita Galkin](https://github.com/galkin), [Parambir Singh](https://github.com/parambirs), [Sebastian Silbermann](https://github.com/eps1lon), [Thomas den Hollander](https://github.com/ThomasdenH), [Wilco Bakker](https://github.com/WilcoBakker), [wwwy3y3](https://github.com/wwwy3y3), [Samuel Ainsworth](https://github.com/samuela), [Kyle Uehlein](https://github.com/kuehlein), [Thanik Bhongbhibhat](https://github.com/bhongy), [Marcin Kopacz](https://github.com/chyzwar), [Trivikram Kamat](https://github.com/trivikr), [Junxiao Shi](https://github.com/yoursunny), [Ilia Baryshnikov](https://github.com/qwelias), [ExE Boss](https://github.com/ExE-Boss), [Piotr Błażejewicz](https://github.com/peterblazejewicz), [Anna Henningsen](https://github.com/addaleax), [Victor Perin](https://github.com/victorperin), [Yongsheng Zhang](https://github.com/ZYSzys), [NodeJS Contributors](https://github.com/NodeJS), [Linus Unnebäck](https://github.com/LinusU), [wafuwafu13](https://github.com/wafuwafu13), [Matteo Collina](https://github.com/mcollina), and [Dmitry Semigradsky](https://github.com/Semigradsky). +These definitions were written by [Microsoft TypeScript](https://github.com/Microsoft), [Alberto Schiabel](https://github.com/jkomyno), [Andrew Makarov](https://github.com/r3nya), [Benjamin Toueg](https://github.com/btoueg), [David Junger](https://github.com/touffy), [Mohsen Azimi](https://github.com/mohsen1), [Nikita Galkin](https://github.com/galkin), [Sebastian Silbermann](https://github.com/eps1lon), [Wilco Bakker](https://github.com/WilcoBakker), [Marcin Kopacz](https://github.com/chyzwar), [Trivikram Kamat](https://github.com/trivikr), [Junxiao Shi](https://github.com/yoursunny), [Ilia Baryshnikov](https://github.com/qwelias), [ExE Boss](https://github.com/ExE-Boss), [Piotr Błażejewicz](https://github.com/peterblazejewicz), [Anna Henningsen](https://github.com/addaleax), [Victor Perin](https://github.com/victorperin), [NodeJS Contributors](https://github.com/NodeJS), [Linus Unnebäck](https://github.com/LinusU), [wafuwafu13](https://github.com/wafuwafu13), [Matteo Collina](https://github.com/mcollina), [Dmitry Semigradsky](https://github.com/Semigradsky), [René](https://github.com/Renegade334), and [Yagiz Nizipli](https://github.com/anonrig). diff --git a/backend/node_modules/@types/node/assert.d.ts b/backend/node_modules/@types/node/assert.d.ts index 4e465c5..cd6d6df 100644 --- a/backend/node_modules/@types/node/assert.d.ts +++ b/backend/node_modules/@types/node/assert.d.ts @@ -1,20 +1,166 @@ /** * The `node:assert` module provides a set of assertion functions for verifying * invariants. - * @see [source](https://github.com/nodejs/node/blob/v20.13.1/lib/assert.js) + * @see [source](https://github.com/nodejs/node/blob/v24.x/lib/assert.js) */ declare module "assert" { + import strict = require("assert/strict"); /** - * An alias of {@link ok}. + * An alias of {@link assert.ok}. * @since v0.5.9 * @param value The input that is checked for being truthy. */ function assert(value: unknown, message?: string | Error): asserts value; + const kOptions: unique symbol; namespace assert { + type AssertMethodNames = + | "deepEqual" + | "deepStrictEqual" + | "doesNotMatch" + | "doesNotReject" + | "doesNotThrow" + | "equal" + | "fail" + | "ifError" + | "match" + | "notDeepEqual" + | "notDeepStrictEqual" + | "notEqual" + | "notStrictEqual" + | "ok" + | "partialDeepStrictEqual" + | "rejects" + | "strictEqual" + | "throws"; + interface AssertOptions { + /** + * If set to `'full'`, shows the full diff in assertion errors. + * @default 'simple' + */ + diff?: "simple" | "full" | undefined; + /** + * If set to `true`, non-strict methods behave like their + * corresponding strict methods. + * @default true + */ + strict?: boolean | undefined; + /** + * If set to `true`, skips prototype and constructor + * comparison in deep equality checks. + * @since v24.9.0 + * @default false + */ + skipPrototype?: boolean | undefined; + } + interface Assert extends Pick { + readonly [kOptions]: AssertOptions & { strict: false }; + } + interface AssertStrict extends Pick { + readonly [kOptions]: AssertOptions & { strict: true }; + } + /** + * The `Assert` class allows creating independent assertion instances with custom options. + * @since v24.6.0 + */ + var Assert: { + /** + * Creates a new assertion instance. The `diff` option controls the verbosity of diffs in assertion error messages. + * + * ```js + * const { Assert } = require('node:assert'); + * const assertInstance = new Assert({ diff: 'full' }); + * assertInstance.deepStrictEqual({ a: 1 }, { a: 2 }); + * // Shows a full diff in the error message. + * ``` + * + * **Important**: When destructuring assertion methods from an `Assert` instance, + * the methods lose their connection to the instance's configuration options (such + * as `diff`, `strict`, and `skipPrototype` settings). + * The destructured methods will fall back to default behavior instead. + * + * ```js + * const myAssert = new Assert({ diff: 'full' }); + * + * // This works as expected - uses 'full' diff + * myAssert.strictEqual({ a: 1 }, { b: { c: 1 } }); + * + * // This loses the 'full' diff setting - falls back to default 'simple' diff + * const { strictEqual } = myAssert; + * strictEqual({ a: 1 }, { b: { c: 1 } }); + * ``` + * + * The `skipPrototype` option affects all deep equality methods: + * + * ```js + * class Foo { + * constructor(a) { + * this.a = a; + * } + * } + * + * class Bar { + * constructor(a) { + * this.a = a; + * } + * } + * + * const foo = new Foo(1); + * const bar = new Bar(1); + * + * // Default behavior - fails due to different constructors + * const assert1 = new Assert(); + * assert1.deepStrictEqual(foo, bar); // AssertionError + * + * // Skip prototype comparison - passes if properties are equal + * const assert2 = new Assert({ skipPrototype: true }); + * assert2.deepStrictEqual(foo, bar); // OK + * ``` + * + * When destructured, methods lose access to the instance's `this` context and revert to default assertion behavior + * (diff: 'simple', non-strict mode). + * To maintain custom options when using destructured methods, avoid + * destructuring and call methods directly on the instance. + * @since v24.6.0 + */ + new( + options?: AssertOptions & { strict?: true | undefined }, + ): AssertStrict; + new( + options: AssertOptions, + ): Assert; + }; + interface AssertionErrorOptions { + /** + * If provided, the error message is set to this value. + */ + message?: string | undefined; + /** + * The `actual` property on the error instance. + */ + actual?: unknown; + /** + * The `expected` property on the error instance. + */ + expected?: unknown; + /** + * The `operator` property on the error instance. + */ + operator?: string | undefined; + /** + * If provided, the generated stack trace omits frames before this function. + */ + stackStartFn?: Function | undefined; + /** + * If set to `'full'`, shows the full diff in assertion errors. + * @default 'simple' + */ + diff?: "simple" | "full" | undefined; + } /** * Indicates the failure of an assertion. All errors thrown by the `node:assert` module will be instances of the `AssertionError` class. */ class AssertionError extends Error { + constructor(options: AssertionErrorOptions); /** * Set to the `actual` argument for methods such as {@link assert.strictEqual()}. */ @@ -23,10 +169,6 @@ declare module "assert" { * Set to the `expected` argument for methods such as {@link assert.strictEqual()}. */ expected: unknown; - /** - * Set to the passed in operator value. - */ - operator: string; /** * Indicates if the message was auto-generated (`true`) or not. */ @@ -35,19 +177,10 @@ declare module "assert" { * Value is always `ERR_ASSERTION` to show that the error is an assertion error. */ code: "ERR_ASSERTION"; - constructor(options?: { - /** If provided, the error message is set to this value. */ - message?: string | undefined; - /** The `actual` property on the error instance. */ - actual?: unknown | undefined; - /** The `expected` property on the error instance. */ - expected?: unknown | undefined; - /** The `operator` property on the error instance. */ - operator?: string | undefined; - /** If provided, the generated stack trace omits frames before this function. */ - // eslint-disable-next-line @typescript-eslint/ban-types - stackStartFn?: Function | undefined; - }); + /** + * Set to the passed in operator value. + */ + operator: string; } /** * This feature is deprecated and will be removed in a future version. @@ -79,7 +212,9 @@ declare module "assert" { * @return A function that wraps `fn`. */ calls(exact?: number): () => void; - calls any>(fn?: Func, exact?: number): Func; + calls(fn: undefined, exact?: number): () => void; + calls any>(fn: Func, exact?: number): Func; + calls any>(fn?: Func, exact?: number): Func | (() => void); /** * Example: * @@ -226,7 +361,7 @@ declare module "assert" { expected: unknown, message?: string | Error, operator?: string, - // eslint-disable-next-line @typescript-eslint/ban-types + // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type stackStartFn?: Function, ): never; /** @@ -796,7 +931,7 @@ declare module "assert" { * check that the promise is rejected. * * If `asyncFn` is a function and it throws an error synchronously, `assert.rejects()` will return a rejected `Promise` with that error. If the - * function does not return a promise, `assert.rejects()` will return a rejected `Promise` with an [ERR_INVALID_RETURN_VALUE](https://nodejs.org/docs/latest-v20.x/api/errors.html#err_invalid_return_value) + * function does not return a promise, `assert.rejects()` will return a rejected `Promise` with an [ERR_INVALID_RETURN_VALUE](https://nodejs.org/docs/latest-v24.x/api/errors.html#err_invalid_return_value) * error. In both cases the error handler is skipped. * * Besides the async nature to await the completion behaves identically to {@link throws}. @@ -866,7 +1001,7 @@ declare module "assert" { * * If `asyncFn` is a function and it throws an error synchronously, `assert.doesNotReject()` will return a rejected `Promise` with that error. If * the function does not return a promise, `assert.doesNotReject()` will return a - * rejected `Promise` with an [ERR_INVALID_RETURN_VALUE](https://nodejs.org/docs/latest-v20.x/api/errors.html#err_invalid_return_value) error. In both cases + * rejected `Promise` with an [ERR_INVALID_RETURN_VALUE](https://nodejs.org/docs/latest-v24.x/api/errors.html#err_invalid_return_value) error. In both cases * the error handler is skipped. * * Using `assert.doesNotReject()` is actually not useful because there is little @@ -929,7 +1064,7 @@ declare module "assert" { * If the values do not match, or if the `string` argument is of another type than `string`, an `{@link AssertionError}` is thrown with a `message` property set equal * to the value of the `message` parameter. If the `message` parameter is * undefined, a default error message is assigned. If the `message` parameter is an - * instance of an [Error](https://nodejs.org/docs/latest-v20.x/api/errors.html#class-error) then it will be thrown instead of the `{@link AssertionError}`. + * instance of an [Error](https://nodejs.org/docs/latest-v24.x/api/errors.html#class-error) then it will be thrown instead of the `{@link AssertionError}`. * @since v13.6.0, v12.16.0 */ function match(value: string, regExp: RegExp, message?: string | Error): void; @@ -952,85 +1087,25 @@ declare module "assert" { * If the values do match, or if the `string` argument is of another type than `string`, an `{@link AssertionError}` is thrown with a `message` property set equal * to the value of the `message` parameter. If the `message` parameter is * undefined, a default error message is assigned. If the `message` parameter is an - * instance of an [Error](https://nodejs.org/docs/latest-v20.x/api/errors.html#class-error) then it will be thrown instead of the `{@link AssertionError}`. + * instance of an [Error](https://nodejs.org/docs/latest-v24.x/api/errors.html#class-error) then it will be thrown instead of the `{@link AssertionError}`. * @since v13.6.0, v12.16.0 */ function doesNotMatch(value: string, regExp: RegExp, message?: string | Error): void; /** - * In strict assertion mode, non-strict methods behave like their corresponding strict methods. For example, - * {@link deepEqual} will behave like {@link deepStrictEqual}. + * Tests for partial deep equality between the `actual` and `expected` parameters. + * "Deep" equality means that the enumerable "own" properties of child objects + * are recursively evaluated also by the following rules. "Partial" equality means + * that only properties that exist on the `expected` parameter are going to be + * compared. * - * In strict assertion mode, error messages for objects display a diff. In legacy assertion mode, error - * messages for objects display the objects, often truncated. - * - * To use strict assertion mode: - * - * ```js - * import { strict as assert } from 'node:assert';COPY - * import assert from 'node:assert/strict'; - * ``` - * - * Example error diff: - * - * ```js - * import { strict as assert } from 'node:assert'; - * - * assert.deepEqual([[[1, 2, 3]], 4, 5], [[[1, 2, '3']], 4, 5]); - * // AssertionError: Expected inputs to be strictly deep-equal: - * // + actual - expected ... Lines skipped - * // - * // [ - * // [ - * // ... - * // 2, - * // + 3 - * // - '3' - * // ], - * // ... - * // 5 - * // ] - * ``` - * - * To deactivate the colors, use the `NO_COLOR` or `NODE_DISABLE_COLORS` environment variables. This will also - * deactivate the colors in the REPL. For more on color support in terminal environments, read the tty - * `getColorDepth()` documentation. - * - * @since v15.0.0, v13.9.0, v12.16.2, v9.9.0 + * This method always passes the same test cases as `assert.deepStrictEqual()`, + * behaving as a super set of it. + * @since v22.13.0 */ - namespace strict { - type AssertionError = assert.AssertionError; - type AssertPredicate = assert.AssertPredicate; - type CallTrackerCall = assert.CallTrackerCall; - type CallTrackerReportInformation = assert.CallTrackerReportInformation; - } - const strict: - & Omit< - typeof assert, - | "equal" - | "notEqual" - | "deepEqual" - | "notDeepEqual" - | "ok" - | "strictEqual" - | "deepStrictEqual" - | "ifError" - | "strict" - > - & { - (value: unknown, message?: string | Error): asserts value; - equal: typeof strictEqual; - notEqual: typeof notStrictEqual; - deepEqual: typeof deepStrictEqual; - notDeepEqual: typeof notDeepStrictEqual; - // Mapped types and assertion functions are incompatible? - // TS2775: Assertions require every name in the call target - // to be declared with an explicit type annotation. - ok: typeof ok; - strictEqual: typeof strictEqual; - deepStrictEqual: typeof deepStrictEqual; - ifError: typeof ifError; - strict: typeof strict; - }; + function partialDeepStrictEqual(actual: unknown, expected: unknown, message?: string | Error): void; + } + namespace assert { + export { strict }; } export = assert; } diff --git a/backend/node_modules/@types/node/assert/strict.d.ts b/backend/node_modules/@types/node/assert/strict.d.ts index f333913..4ed7395 100644 --- a/backend/node_modules/@types/node/assert/strict.d.ts +++ b/backend/node_modules/@types/node/assert/strict.d.ts @@ -1,8 +1,111 @@ +/** + * In strict assertion mode, non-strict methods behave like their corresponding + * strict methods. For example, `assert.deepEqual()` will behave like + * `assert.deepStrictEqual()`. + * + * In strict assertion mode, error messages for objects display a diff. In legacy + * assertion mode, error messages for objects display the objects, often truncated. + * + * To use strict assertion mode: + * + * ```js + * import { strict as assert } from 'node:assert'; + * ``` + * + * ```js + * import assert from 'node:assert/strict'; + * ``` + * + * Example error diff: + * + * ```js + * import { strict as assert } from 'node:assert'; + * + * assert.deepEqual([[[1, 2, 3]], 4, 5], [[[1, 2, '3']], 4, 5]); + * // AssertionError: Expected inputs to be strictly deep-equal: + * // + actual - expected ... Lines skipped + * // + * // [ + * // [ + * // ... + * // 2, + * // + 3 + * // - '3' + * // ], + * // ... + * // 5 + * // ] + * ``` + * + * To deactivate the colors, use the `NO_COLOR` or `NODE_DISABLE_COLORS` + * environment variables. This will also deactivate the colors in the REPL. For + * more on color support in terminal environments, read the tty + * [`getColorDepth()`](https://nodejs.org/docs/latest-v24.x/api/tty.html#writestreamgetcolordepthenv) documentation. + * @since v15.0.0 + * @see [source](https://github.com/nodejs/node/blob/v24.x/lib/assert/strict.js) + */ declare module "assert/strict" { - import { strict } from "node:assert"; + import { + Assert, + AssertionError, + AssertionErrorOptions, + AssertOptions, + AssertPredicate, + AssertStrict, + CallTracker, + CallTrackerCall, + CallTrackerReportInformation, + deepStrictEqual, + doesNotMatch, + doesNotReject, + doesNotThrow, + fail, + ifError, + match, + notDeepStrictEqual, + notStrictEqual, + ok, + partialDeepStrictEqual, + rejects, + strictEqual, + throws, + } from "node:assert"; + function strict(value: unknown, message?: string | Error): asserts value; + namespace strict { + export { + Assert, + AssertionError, + AssertionErrorOptions, + AssertOptions, + AssertPredicate, + AssertStrict, + CallTracker, + CallTrackerCall, + CallTrackerReportInformation, + deepStrictEqual, + deepStrictEqual as deepEqual, + doesNotMatch, + doesNotReject, + doesNotThrow, + fail, + ifError, + match, + notDeepStrictEqual, + notDeepStrictEqual as notDeepEqual, + notStrictEqual, + notStrictEqual as notEqual, + ok, + partialDeepStrictEqual, + rejects, + strict, + strictEqual, + strictEqual as equal, + throws, + }; + } export = strict; } declare module "node:assert/strict" { - import { strict } from "node:assert"; + import strict = require("assert/strict"); export = strict; } diff --git a/backend/node_modules/@types/node/async_hooks.d.ts b/backend/node_modules/@types/node/async_hooks.d.ts index f5432e2..2377689 100644 --- a/backend/node_modules/@types/node/async_hooks.d.ts +++ b/backend/node_modules/@types/node/async_hooks.d.ts @@ -2,8 +2,8 @@ * We strongly discourage the use of the `async_hooks` API. * Other APIs that can cover most of its use cases include: * - * * [`AsyncLocalStorage`](https://nodejs.org/docs/latest-v20.x/api/async_context.html#class-asynclocalstorage) tracks async context - * * [`process.getActiveResourcesInfo()`](https://nodejs.org/docs/latest-v20.x/api/process.html#processgetactiveresourcesinfo) tracks active resources + * * [`AsyncLocalStorage`](https://nodejs.org/docs/latest-v24.x/api/async_context.html#class-asynclocalstorage) tracks async context + * * [`process.getActiveResourcesInfo()`](https://nodejs.org/docs/latest-v24.x/api/process.html#processgetactiveresourcesinfo) tracks active resources * * The `node:async_hooks` module provides an API to track asynchronous resources. * It can be accessed using: @@ -12,7 +12,7 @@ * import async_hooks from 'node:async_hooks'; * ``` * @experimental - * @see [source](https://github.com/nodejs/node/blob/v20.13.1/lib/async_hooks.js) + * @see [source](https://github.com/nodejs/node/blob/v24.x/lib/async_hooks.js) */ declare module "async_hooks" { /** @@ -44,7 +44,7 @@ declare module "async_hooks" { * ``` * * Promise contexts may not get precise `executionAsyncIds` by default. - * See the section on [promise execution tracking](https://nodejs.org/docs/latest-v20.x/api/async_hooks.html#promise-execution-tracking). + * See the section on [promise execution tracking](https://nodejs.org/docs/latest-v24.x/api/async_hooks.html#promise-execution-tracking). * @since v8.1.0 * @return The `asyncId` of the current execution context. Useful to track when something calls. */ @@ -77,7 +77,7 @@ declare module "async_hooks" { * executionAsyncId, * executionAsyncResource, * createHook, - * } from 'async_hooks'; + * } from 'node:async_hooks'; * const sym = Symbol('state'); // Private symbol to avoid pollution * * createHook({ @@ -117,7 +117,7 @@ declare module "async_hooks" { * ``` * * Promise contexts may not get valid `triggerAsyncId`s by default. See - * the section on [promise execution tracking](https://nodejs.org/docs/latest-v20.x/api/async_hooks.html#promise-execution-tracking). + * the section on [promise execution tracking](https://nodejs.org/docs/latest-v24.x/api/async_hooks.html#promise-execution-tracking). * @return The ID of the resource responsible for calling the callback that is currently being executed. */ function triggerAsyncId(): number; @@ -320,6 +320,16 @@ declare module "async_hooks" { */ triggerAsyncId(): number; } + interface AsyncLocalStorageOptions { + /** + * The default value to be used when no store is provided. + */ + defaultValue?: any; + /** + * A name for the `AsyncLocalStorage` value. + */ + name?: string | undefined; + } /** * This class creates stores that stay coherent through asynchronous operations. * @@ -358,8 +368,8 @@ declare module "async_hooks" { * http.get('http://localhost:8080'); * // Prints: * // 0: start - * // 1: start * // 0: finish + * // 1: start * // 1: finish * ``` * @@ -369,10 +379,14 @@ declare module "async_hooks" { * @since v13.10.0, v12.17.0 */ class AsyncLocalStorage { + /** + * Creates a new instance of `AsyncLocalStorage`. Store is only provided within a + * `run()` call or after an `enterWith()` call. + */ + constructor(options?: AsyncLocalStorageOptions); /** * Binds the given function to the current execution context. * @since v19.8.0 - * @experimental * @param fn The function to bind to the current execution context. * @return A new function that calls `fn` within the captured execution context. */ @@ -403,7 +417,6 @@ declare module "async_hooks" { * console.log(asyncLocalStorage.run(321, () => foo.get())); // returns 123 * ``` * @since v19.8.0 - * @experimental * @return A new function with the signature `(fn: (...args) : R, ...args) : R`. */ static snapshot(): (fn: (...args: TArgs) => R, ...args: TArgs) => R; @@ -432,6 +445,11 @@ declare module "async_hooks" { * @since v13.10.0, v12.17.0 */ getStore(): T | undefined; + /** + * The name of the `AsyncLocalStorage` instance if provided. + * @since v24.0.0 + */ + readonly name: string; /** * Runs a function synchronously within a context and returns its * return value. The store is not accessible outside of the callback function. @@ -535,6 +553,70 @@ declare module "async_hooks" { */ enterWith(store: T): void; } + /** + * @since v17.2.0, v16.14.0 + * @return A map of provider types to the corresponding numeric id. + * This map contains all the event types that might be emitted by the `async_hooks.init()` event. + */ + namespace asyncWrapProviders { + const NONE: number; + const DIRHANDLE: number; + const DNSCHANNEL: number; + const ELDHISTOGRAM: number; + const FILEHANDLE: number; + const FILEHANDLECLOSEREQ: number; + const FIXEDSIZEBLOBCOPY: number; + const FSEVENTWRAP: number; + const FSREQCALLBACK: number; + const FSREQPROMISE: number; + const GETADDRINFOREQWRAP: number; + const GETNAMEINFOREQWRAP: number; + const HEAPSNAPSHOT: number; + const HTTP2SESSION: number; + const HTTP2STREAM: number; + const HTTP2PING: number; + const HTTP2SETTINGS: number; + const HTTPINCOMINGMESSAGE: number; + const HTTPCLIENTREQUEST: number; + const JSSTREAM: number; + const JSUDPWRAP: number; + const MESSAGEPORT: number; + const PIPECONNECTWRAP: number; + const PIPESERVERWRAP: number; + const PIPEWRAP: number; + const PROCESSWRAP: number; + const PROMISE: number; + const QUERYWRAP: number; + const SHUTDOWNWRAP: number; + const SIGNALWRAP: number; + const STATWATCHER: number; + const STREAMPIPE: number; + const TCPCONNECTWRAP: number; + const TCPSERVERWRAP: number; + const TCPWRAP: number; + const TTYWRAP: number; + const UDPSENDWRAP: number; + const UDPWRAP: number; + const SIGINTWATCHDOG: number; + const WORKER: number; + const WORKERHEAPSNAPSHOT: number; + const WRITEWRAP: number; + const ZLIB: number; + const CHECKPRIMEREQUEST: number; + const PBKDF2REQUEST: number; + const KEYPAIRGENREQUEST: number; + const KEYGENREQUEST: number; + const KEYEXPORTREQUEST: number; + const CIPHERREQUEST: number; + const DERIVEBITSREQUEST: number; + const HASHREQUEST: number; + const RANDOMBYTESREQUEST: number; + const RANDOMPRIMEREQUEST: number; + const SCRYPTREQUEST: number; + const SIGNREQUEST: number; + const TLSWRAP: number; + const VERIFYREQUEST: number; + } } declare module "node:async_hooks" { export * from "async_hooks"; diff --git a/backend/node_modules/@types/node/buffer.d.ts b/backend/node_modules/@types/node/buffer.d.ts index 5d6c97d..9a62ccf 100644 --- a/backend/node_modules/@types/node/buffer.d.ts +++ b/backend/node_modules/@types/node/buffer.d.ts @@ -1,3 +1,8 @@ +// If lib.dom.d.ts or lib.webworker.d.ts is loaded, then use the global types. +// Otherwise, use the types from node. +type _Blob = typeof globalThis extends { onmessage: any; Blob: any } ? {} : import("buffer").Blob; +type _File = typeof globalThis extends { onmessage: any; File: any } ? {} : import("buffer").File; + /** * `Buffer` objects are used to represent a fixed-length sequence of bytes. Many * Node.js APIs support `Buffer`s. @@ -41,7 +46,7 @@ * // Creates a Buffer containing the Latin-1 bytes [0x74, 0xe9, 0x73, 0x74]. * const buf7 = Buffer.from('tést', 'latin1'); * ``` - * @see [source](https://github.com/nodejs/node/blob/v20.13.1/lib/buffer.js) + * @see [source](https://github.com/nodejs/node/blob/v24.x/lib/buffer.js) */ declare module "buffer" { import { BinaryLike } from "node:crypto"; @@ -54,7 +59,7 @@ declare module "buffer" { * @since v19.4.0, v18.14.0 * @param input The input to validate. */ - export function isUtf8(input: Buffer | ArrayBuffer | NodeJS.TypedArray): boolean; + export function isUtf8(input: ArrayBuffer | NodeJS.TypedArray): boolean; /** * This function returns `true` if `input` contains only valid ASCII-encoded data, * including the case in which `input` is empty. @@ -63,8 +68,8 @@ declare module "buffer" { * @since v19.6.0, v18.15.0 * @param input The input to validate. */ - export function isAscii(input: Buffer | ArrayBuffer | NodeJS.TypedArray): boolean; - export const INSPECT_MAX_BYTES: number; + export function isAscii(input: ArrayBuffer | NodeJS.TypedArray): boolean; + export let INSPECT_MAX_BYTES: number; export const kMaxLength: number; export const kStringMaxLength: number; export const constants: { @@ -108,28 +113,26 @@ declare module "buffer" { * @param fromEnc The current encoding. * @param toEnc To target encoding. */ - export function transcode(source: Uint8Array, fromEnc: TranscodeEncoding, toEnc: TranscodeEncoding): Buffer; - export const SlowBuffer: { - /** @deprecated since v6.0.0, use `Buffer.allocUnsafeSlow()` */ - new(size: number): Buffer; - prototype: Buffer; - }; + export function transcode( + source: Uint8Array, + fromEnc: TranscodeEncoding, + toEnc: TranscodeEncoding, + ): NonSharedBuffer; /** * Resolves a `'blob:nodedata:...'` an associated `Blob` object registered using * a prior call to `URL.createObjectURL()`. * @since v16.7.0 - * @experimental * @param id A `'blob:nodedata:...` URL string returned by a prior call to `URL.createObjectURL()`. */ export function resolveObjectURL(id: string): Blob | undefined; - export { Buffer }; + export { type AllowSharedBuffer, Buffer, type NonSharedBuffer }; /** * @experimental */ export interface BlobOptions { /** * One of either `'transparent'` or `'native'`. When set to `'native'`, line endings in string source parts - * will be converted to the platform native line-ending as specified by `require('node:os').EOL`. + * will be converted to the platform native line-ending as specified by `import { EOL } from 'node:os'`. */ endings?: "transparent" | "native"; /** @@ -140,7 +143,7 @@ declare module "buffer" { type?: string | undefined; } /** - * A [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) encapsulates immutable, raw data that can be safely shared across + * A `Blob` encapsulates immutable, raw data that can be safely shared across * multiple worker threads. * @since v15.7.0, v14.18.0 */ @@ -170,6 +173,17 @@ declare module "buffer" { * @since v15.7.0, v14.18.0 */ arrayBuffer(): Promise; + /** + * The `blob.bytes()` method returns the byte of the `Blob` object as a `Promise`. + * + * ```js + * const blob = new Blob(['hello']); + * blob.bytes().then((bytes) => { + * console.log(bytes); // Outputs: Uint8Array(5) [ 104, 101, 108, 108, 111 ] + * }); + * ``` + */ + bytes(): Promise; /** * Creates and returns a new `Blob` containing a subset of this `Blob` objects * data. The original `Blob` is not altered. @@ -194,7 +208,7 @@ declare module "buffer" { export interface FileOptions { /** * One of either `'transparent'` or `'native'`. When set to `'native'`, line endings in string source parts will be - * converted to the platform native line-ending as specified by `require('node:os').EOL`. + * converted to the platform native line-ending as specified by `import { EOL } from 'node:os'`. */ endings?: "native" | "transparent"; /** The File content-type. */ @@ -221,10 +235,10 @@ declare module "buffer" { } export import atob = globalThis.atob; export import btoa = globalThis.btoa; - import { Blob as NodeBlob } from "buffer"; - // This conditional type will be the existing global Blob in a browser, or - // the copy below in a Node environment. - type __Blob = typeof globalThis extends { onmessage: any; Blob: any } ? {} : NodeBlob; + export type WithImplicitCoercion = + | T + | { valueOf(): T } + | (T extends string ? { [Symbol.toPrimitive](hint: "string"): T } : never); global { namespace NodeJS { export { BufferEncoding }; @@ -243,111 +257,15 @@ declare module "buffer" { | "latin1" | "binary" | "hex"; - type WithImplicitCoercion = - | T - | { - valueOf(): T; - }; /** * Raw data is stored in instances of the Buffer class. * A Buffer is similar to an array of integers but corresponds to a raw memory allocation outside the V8 heap. A Buffer cannot be resized. * Valid string encodings: 'ascii'|'utf8'|'utf16le'|'ucs2'(alias of 'utf16le')|'base64'|'base64url'|'binary'(deprecated)|'hex' */ interface BufferConstructor { - /** - * Allocates a new buffer containing the given {str}. - * - * @param str String to store in buffer. - * @param encoding encoding to use, optional. Default is 'utf8' - * @deprecated since v10.0.0 - Use `Buffer.from(string[, encoding])` instead. - */ - new(str: string, encoding?: BufferEncoding): Buffer; - /** - * Allocates a new buffer of {size} octets. - * - * @param size count of octets to allocate. - * @deprecated since v10.0.0 - Use `Buffer.alloc()` instead (also see `Buffer.allocUnsafe()`). - */ - new(size: number): Buffer; - /** - * Allocates a new buffer containing the given {array} of octets. - * - * @param array The octets to store. - * @deprecated since v10.0.0 - Use `Buffer.from(array)` instead. - */ - new(array: Uint8Array): Buffer; - /** - * Produces a Buffer backed by the same allocated memory as - * the given {ArrayBuffer}/{SharedArrayBuffer}. - * - * @param arrayBuffer The ArrayBuffer with which to share memory. - * @deprecated since v10.0.0 - Use `Buffer.from(arrayBuffer[, byteOffset[, length]])` instead. - */ - new(arrayBuffer: ArrayBuffer | SharedArrayBuffer): Buffer; - /** - * Allocates a new buffer containing the given {array} of octets. - * - * @param array The octets to store. - * @deprecated since v10.0.0 - Use `Buffer.from(array)` instead. - */ - new(array: readonly any[]): Buffer; - /** - * Copies the passed {buffer} data onto a new {Buffer} instance. - * - * @param buffer The buffer to copy. - * @deprecated since v10.0.0 - Use `Buffer.from(buffer)` instead. - */ - new(buffer: Buffer): Buffer; - /** - * Allocates a new `Buffer` using an `array` of bytes in the range `0` – `255`. - * Array entries outside that range will be truncated to fit into it. - * - * ```js - * import { Buffer } from 'node:buffer'; - * - * // Creates a new Buffer containing the UTF-8 bytes of the string 'buffer'. - * const buf = Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]); - * ``` - * - * If `array` is an `Array`\-like object (that is, one with a `length` property of - * type `number`), it is treated as if it is an array, unless it is a `Buffer` or - * a `Uint8Array`. This means all other `TypedArray` variants get treated as an `Array`. To create a `Buffer` from the bytes backing a `TypedArray`, use `Buffer.copyBytesFrom()`. - * - * A `TypeError` will be thrown if `array` is not an `Array` or another type - * appropriate for `Buffer.from()` variants. - * - * `Buffer.from(array)` and `Buffer.from(string)` may also use the internal `Buffer` pool like `Buffer.allocUnsafe()` does. - * @since v5.10.0 - */ - from( - arrayBuffer: WithImplicitCoercion, - byteOffset?: number, - length?: number, - ): Buffer; - /** - * Creates a new Buffer using the passed {data} - * @param data data to create a new Buffer - */ - from(data: Uint8Array | readonly number[]): Buffer; - from(data: WithImplicitCoercion): Buffer; - /** - * Creates a new Buffer containing the given JavaScript string {str}. - * If provided, the {encoding} parameter identifies the character encoding. - * If not provided, {encoding} defaults to 'utf8'. - */ - from( - str: - | WithImplicitCoercion - | { - [Symbol.toPrimitive](hint: "string"): string; - }, - encoding?: BufferEncoding, - ): Buffer; - /** - * Creates a new Buffer using the passed {data} - * @param values to create a new Buffer - */ - of(...items: number[]): Buffer; + // see buffer.buffer.d.ts for implementation specific to TypeScript 5.7 and later + // see ts5.6/buffer.buffer.d.ts for implementation specific to TypeScript 5.6 and earlier + /** * Returns `true` if `obj` is a `Buffer`, `false` otherwise. * @@ -416,65 +334,9 @@ declare module "buffer" { * @return The number of bytes contained within `string`. */ byteLength( - string: string | Buffer | NodeJS.ArrayBufferView | ArrayBuffer | SharedArrayBuffer, + string: string | NodeJS.ArrayBufferView | ArrayBufferLike, encoding?: BufferEncoding, ): number; - /** - * Returns a new `Buffer` which is the result of concatenating all the `Buffer` instances in the `list` together. - * - * If the list has no items, or if the `totalLength` is 0, then a new zero-length `Buffer` is returned. - * - * If `totalLength` is not provided, it is calculated from the `Buffer` instances - * in `list` by adding their lengths. - * - * If `totalLength` is provided, it is coerced to an unsigned integer. If the - * combined length of the `Buffer`s in `list` exceeds `totalLength`, the result is - * truncated to `totalLength`. - * - * ```js - * import { Buffer } from 'node:buffer'; - * - * // Create a single `Buffer` from a list of three `Buffer` instances. - * - * const buf1 = Buffer.alloc(10); - * const buf2 = Buffer.alloc(14); - * const buf3 = Buffer.alloc(18); - * const totalLength = buf1.length + buf2.length + buf3.length; - * - * console.log(totalLength); - * // Prints: 42 - * - * const bufA = Buffer.concat([buf1, buf2, buf3], totalLength); - * - * console.log(bufA); - * // Prints: - * console.log(bufA.length); - * // Prints: 42 - * ``` - * - * `Buffer.concat()` may also use the internal `Buffer` pool like `Buffer.allocUnsafe()` does. - * @since v0.7.11 - * @param list List of `Buffer` or {@link Uint8Array} instances to concatenate. - * @param totalLength Total length of the `Buffer` instances in `list` when concatenated. - */ - concat(list: readonly Uint8Array[], totalLength?: number): Buffer; - /** - * Copies the underlying memory of `view` into a new `Buffer`. - * - * ```js - * const u16 = new Uint16Array([0, 0xffff]); - * const buf = Buffer.copyBytesFrom(u16, 1, 1); - * u16[1] = 0; - * console.log(buf.length); // 2 - * console.log(buf[0]); // 255 - * console.log(buf[1]); // 255 - * ``` - * @since v19.8.0 - * @param view The {TypedArray} to copy. - * @param [offset=0] The starting offset within `view`. - * @param [length=view.length - offset] The number of elements from `view` to copy. - */ - copyBytesFrom(view: NodeJS.TypedArray, offset?: number, length?: number): Buffer; /** * Compares `buf1` to `buf2`, typically for the purpose of sorting arrays of `Buffer` instances. This is equivalent to calling `buf1.compare(buf2)`. * @@ -493,135 +355,6 @@ declare module "buffer" { * @return Either `-1`, `0`, or `1`, depending on the result of the comparison. See `compare` for details. */ compare(buf1: Uint8Array, buf2: Uint8Array): -1 | 0 | 1; - /** - * Allocates a new `Buffer` of `size` bytes. If `fill` is `undefined`, the`Buffer` will be zero-filled. - * - * ```js - * import { Buffer } from 'node:buffer'; - * - * const buf = Buffer.alloc(5); - * - * console.log(buf); - * // Prints: - * ``` - * - * If `size` is larger than {@link constants.MAX_LENGTH} or smaller than 0, `ERR_OUT_OF_RANGE` is thrown. - * - * If `fill` is specified, the allocated `Buffer` will be initialized by calling `buf.fill(fill)`. - * - * ```js - * import { Buffer } from 'node:buffer'; - * - * const buf = Buffer.alloc(5, 'a'); - * - * console.log(buf); - * // Prints: - * ``` - * - * If both `fill` and `encoding` are specified, the allocated `Buffer` will be - * initialized by calling `buf.fill(fill, encoding)`. - * - * ```js - * import { Buffer } from 'node:buffer'; - * - * const buf = Buffer.alloc(11, 'aGVsbG8gd29ybGQ=', 'base64'); - * - * console.log(buf); - * // Prints: - * ``` - * - * Calling `Buffer.alloc()` can be measurably slower than the alternative `Buffer.allocUnsafe()` but ensures that the newly created `Buffer` instance - * contents will never contain sensitive data from previous allocations, including - * data that might not have been allocated for `Buffer`s. - * - * A `TypeError` will be thrown if `size` is not a number. - * @since v5.10.0 - * @param size The desired length of the new `Buffer`. - * @param [fill=0] A value to pre-fill the new `Buffer` with. - * @param [encoding='utf8'] If `fill` is a string, this is its encoding. - */ - alloc(size: number, fill?: string | Uint8Array | number, encoding?: BufferEncoding): Buffer; - /** - * Allocates a new `Buffer` of `size` bytes. If `size` is larger than {@link constants.MAX_LENGTH} or smaller than 0, `ERR_OUT_OF_RANGE` is thrown. - * - * The underlying memory for `Buffer` instances created in this way is _not_ - * _initialized_. The contents of the newly created `Buffer` are unknown and _may contain sensitive data_. Use `Buffer.alloc()` instead to initialize`Buffer` instances with zeroes. - * - * ```js - * import { Buffer } from 'node:buffer'; - * - * const buf = Buffer.allocUnsafe(10); - * - * console.log(buf); - * // Prints (contents may vary): - * - * buf.fill(0); - * - * console.log(buf); - * // Prints: - * ``` - * - * A `TypeError` will be thrown if `size` is not a number. - * - * The `Buffer` module pre-allocates an internal `Buffer` instance of - * size `Buffer.poolSize` that is used as a pool for the fast allocation of new `Buffer` instances created using `Buffer.allocUnsafe()`, `Buffer.from(array)`, - * and `Buffer.concat()` only when `size` is less than `Buffer.poolSize >>> 1` (floor of `Buffer.poolSize` divided by two). - * - * Use of this pre-allocated internal memory pool is a key difference between - * calling `Buffer.alloc(size, fill)` vs. `Buffer.allocUnsafe(size).fill(fill)`. - * Specifically, `Buffer.alloc(size, fill)` will _never_ use the internal `Buffer`pool, while `Buffer.allocUnsafe(size).fill(fill)`_will_ use the internal`Buffer` pool if `size` is less - * than or equal to half `Buffer.poolSize`. The - * difference is subtle but can be important when an application requires the - * additional performance that `Buffer.allocUnsafe()` provides. - * @since v5.10.0 - * @param size The desired length of the new `Buffer`. - */ - allocUnsafe(size: number): Buffer; - /** - * Allocates a new `Buffer` of `size` bytes. If `size` is larger than {@link constants.MAX_LENGTH} or smaller than 0, `ERR_OUT_OF_RANGE` is thrown. A zero-length `Buffer` is created if - * `size` is 0. - * - * The underlying memory for `Buffer` instances created in this way is _not_ - * _initialized_. The contents of the newly created `Buffer` are unknown and _may contain sensitive data_. Use `buf.fill(0)` to initialize - * such `Buffer` instances with zeroes. - * - * When using `Buffer.allocUnsafe()` to allocate new `Buffer` instances, - * allocations under 4 KiB are sliced from a single pre-allocated `Buffer`. This - * allows applications to avoid the garbage collection overhead of creating many - * individually allocated `Buffer` instances. This approach improves both - * performance and memory usage by eliminating the need to track and clean up as - * many individual `ArrayBuffer` objects. - * - * However, in the case where a developer may need to retain a small chunk of - * memory from a pool for an indeterminate amount of time, it may be appropriate - * to create an un-pooled `Buffer` instance using `Buffer.allocUnsafeSlow()` and - * then copying out the relevant bits. - * - * ```js - * import { Buffer } from 'node:buffer'; - * - * // Need to keep around a few small chunks of memory. - * const store = []; - * - * socket.on('readable', () => { - * let data; - * while (null !== (data = readable.read())) { - * // Allocate for retained data. - * const sb = Buffer.allocUnsafeSlow(10); - * - * // Copy the data into the new allocation. - * data.copy(sb, 0, 0, 10); - * - * store.push(sb); - * } - * }); - * ``` - * - * A `TypeError` will be thrown if `size` is not a number. - * @since v5.12.0 - * @param size The desired length of the new `Buffer`. - */ - allocUnsafeSlow(size: number): Buffer; /** * This is the size (in bytes) of pre-allocated internal `Buffer` instances used * for pooling. This value may be modified. @@ -629,7 +362,10 @@ declare module "buffer" { */ poolSize: number; } - interface Buffer extends Uint8Array { + interface Buffer { + // see buffer.buffer.d.ts for implementation specific to TypeScript 5.7 and later + // see ts5.6/buffer.buffer.d.ts for implementation specific to TypeScript 5.6 and earlier + /** * Writes `string` to `buf` at `offset` according to the character encoding in`encoding`. The `length` parameter is the number of bytes to write. If `buf` did * not contain enough space to fit the entire string, only part of `string` will be @@ -866,100 +602,6 @@ declare module "buffer" { * @return The number of bytes copied. */ copy(target: Uint8Array, targetStart?: number, sourceStart?: number, sourceEnd?: number): number; - /** - * Returns a new `Buffer` that references the same memory as the original, but - * offset and cropped by the `start` and `end` indices. - * - * This method is not compatible with the `Uint8Array.prototype.slice()`, - * which is a superclass of `Buffer`. To copy the slice, use`Uint8Array.prototype.slice()`. - * - * ```js - * import { Buffer } from 'node:buffer'; - * - * const buf = Buffer.from('buffer'); - * - * const copiedBuf = Uint8Array.prototype.slice.call(buf); - * copiedBuf[0]++; - * console.log(copiedBuf.toString()); - * // Prints: cuffer - * - * console.log(buf.toString()); - * // Prints: buffer - * - * // With buf.slice(), the original buffer is modified. - * const notReallyCopiedBuf = buf.slice(); - * notReallyCopiedBuf[0]++; - * console.log(notReallyCopiedBuf.toString()); - * // Prints: cuffer - * console.log(buf.toString()); - * // Also prints: cuffer (!) - * ``` - * @since v0.3.0 - * @deprecated Use `subarray` instead. - * @param [start=0] Where the new `Buffer` will start. - * @param [end=buf.length] Where the new `Buffer` will end (not inclusive). - */ - slice(start?: number, end?: number): Buffer; - /** - * Returns a new `Buffer` that references the same memory as the original, but - * offset and cropped by the `start` and `end` indices. - * - * Specifying `end` greater than `buf.length` will return the same result as - * that of `end` equal to `buf.length`. - * - * This method is inherited from [`TypedArray.prototype.subarray()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/subarray). - * - * Modifying the new `Buffer` slice will modify the memory in the original `Buffer`because the allocated memory of the two objects overlap. - * - * ```js - * import { Buffer } from 'node:buffer'; - * - * // Create a `Buffer` with the ASCII alphabet, take a slice, and modify one byte - * // from the original `Buffer`. - * - * const buf1 = Buffer.allocUnsafe(26); - * - * for (let i = 0; i < 26; i++) { - * // 97 is the decimal ASCII value for 'a'. - * buf1[i] = i + 97; - * } - * - * const buf2 = buf1.subarray(0, 3); - * - * console.log(buf2.toString('ascii', 0, buf2.length)); - * // Prints: abc - * - * buf1[0] = 33; - * - * console.log(buf2.toString('ascii', 0, buf2.length)); - * // Prints: !bc - * ``` - * - * Specifying negative indexes causes the slice to be generated relative to the - * end of `buf` rather than the beginning. - * - * ```js - * import { Buffer } from 'node:buffer'; - * - * const buf = Buffer.from('buffer'); - * - * console.log(buf.subarray(-6, -1).toString()); - * // Prints: buffe - * // (Equivalent to buf.subarray(0, 5).) - * - * console.log(buf.subarray(-6, -2).toString()); - * // Prints: buff - * // (Equivalent to buf.subarray(0, 4).) - * - * console.log(buf.subarray(-5, -2).toString()); - * // Prints: uff - * // (Equivalent to buf.subarray(1, 4).) - * ``` - * @since v3.0.0 - * @param [start=0] Where the new `Buffer` will start. - * @param [end=buf.length] Where the new `Buffer` will end (not inclusive). - */ - subarray(start?: number, end?: number): Buffer; /** * Writes `value` to `buf` at the specified `offset` as big-endian. * @@ -1617,7 +1259,7 @@ declare module "buffer" { * @since v5.10.0 * @return A reference to `buf`. */ - swap16(): Buffer; + swap16(): this; /** * Interprets `buf` as an array of unsigned 32-bit integers and swaps the * byte order _in-place_. Throws `ERR_INVALID_BUFFER_SIZE` if `buf.length` is not a multiple of 4. @@ -1643,7 +1285,7 @@ declare module "buffer" { * @since v5.10.0 * @return A reference to `buf`. */ - swap32(): Buffer; + swap32(): this; /** * Interprets `buf` as an array of 64-bit numbers and swaps byte order _in-place_. * Throws `ERR_INVALID_BUFFER_SIZE` if `buf.length` is not a multiple of 8. @@ -1669,7 +1311,7 @@ declare module "buffer" { * @since v6.3.0 * @return A reference to `buf`. */ - swap64(): Buffer; + swap64(): this; /** * Writes `value` to `buf` at the specified `offset`. `value` must be a * valid unsigned 8-bit integer. Behavior is undefined when `value` is anything @@ -2063,6 +1705,8 @@ declare module "buffer" { * @return A reference to `buf`. */ fill(value: string | Uint8Array | number, offset?: number, end?: number, encoding?: BufferEncoding): this; + fill(value: string | Uint8Array | number, offset: number, encoding: BufferEncoding): this; + fill(value: string | Uint8Array | number, encoding: BufferEncoding): this; /** * If `value` is: * @@ -2132,6 +1776,7 @@ declare module "buffer" { * @return The index of the first occurrence of `value` in `buf`, or `-1` if `buf` does not contain `value`. */ indexOf(value: string | number | Uint8Array, byteOffset?: number, encoding?: BufferEncoding): number; + indexOf(value: string | number | Uint8Array, encoding: BufferEncoding): number; /** * Identical to `buf.indexOf()`, except the last occurrence of `value` is found * rather than the first occurrence. @@ -2200,6 +1845,7 @@ declare module "buffer" { * @return The index of the last occurrence of `value` in `buf`, or `-1` if `buf` does not contain `value`. */ lastIndexOf(value: string | number | Uint8Array, byteOffset?: number, encoding?: BufferEncoding): number; + lastIndexOf(value: string | number | Uint8Array, encoding: BufferEncoding): number; /** * Equivalent to `buf.indexOf() !== -1`. * @@ -2230,6 +1876,7 @@ declare module "buffer" { * @return `true` if `value` was found in `buf`, `false` otherwise. */ includes(value: string | number | Buffer, byteOffset?: number, encoding?: BufferEncoding): boolean; + includes(value: string | number | Buffer, encoding: BufferEncoding): boolean; } var Buffer: BufferConstructor; /** @@ -2264,17 +1911,22 @@ declare module "buffer" { * @param data An ASCII (Latin1) string. */ function btoa(data: string): string; - interface Blob extends __Blob {} + interface Blob extends _Blob {} /** - * `Blob` class is a global reference for `require('node:buffer').Blob` + * `Blob` class is a global reference for `import { Blob } from 'node:buffer'` * https://nodejs.org/api/buffer.html#class-blob * @since v18.0.0 */ - var Blob: typeof globalThis extends { - onmessage: any; - Blob: infer T; - } ? T - : typeof NodeBlob; + var Blob: typeof globalThis extends { onmessage: any; Blob: infer T } ? T + : typeof import("buffer").Blob; + interface File extends _File {} + /** + * `File` class is a global reference for `import { File } from 'node:buffer'` + * https://nodejs.org/api/buffer.html#class-file + * @since v20.0.0 + */ + var File: typeof globalThis extends { onmessage: any; File: infer T } ? T + : typeof import("buffer").File; } } declare module "node:buffer" { diff --git a/backend/node_modules/@types/node/child_process.d.ts b/backend/node_modules/@types/node/child_process.d.ts index b642adc..ecad7d8 100644 --- a/backend/node_modules/@types/node/child_process.d.ts +++ b/backend/node_modules/@types/node/child_process.d.ts @@ -4,7 +4,7 @@ * is primarily provided by the {@link spawn} function: * * ```js - * const { spawn } = require('node:child_process'); + * import { spawn } from 'node:child_process'; * const ls = spawn('ls', ['-lh', '/usr']); * * ls.stdout.on('data', (data) => { @@ -24,7 +24,7 @@ * the parent Node.js process and the spawned subprocess. These pipes have * limited (and platform-specific) capacity. If the subprocess writes to * stdout in excess of that limit without the output being captured, the - * subprocess blocks waiting for the pipe buffer to accept more data. This is + * subprocess blocks, waiting for the pipe buffer to accept more data. This is * identical to the behavior of pipes in the shell. Use the `{ stdio: 'ignore' }` option if the output will not be consumed. * * The command lookup is performed using the `options.env.PATH` environment @@ -63,14 +63,14 @@ * For certain use cases, such as automating shell scripts, the `synchronous counterparts` may be more convenient. In many cases, however, * the synchronous methods can have significant impact on performance due to * stalling the event loop while spawned processes complete. - * @see [source](https://github.com/nodejs/node/blob/v20.13.1/lib/child_process.js) + * @see [source](https://github.com/nodejs/node/blob/v24.x/lib/child_process.js) */ declare module "child_process" { - import { ObjectEncodingOptions } from "node:fs"; + import { NonSharedBuffer } from "node:buffer"; import { Abortable, EventEmitter } from "node:events"; import * as dgram from "node:dgram"; import * as net from "node:net"; - import { Pipe, Readable, Stream, Writable } from "node:stream"; + import { Readable, Stream, Writable } from "node:stream"; import { URL } from "node:url"; type Serializable = string | object | number | boolean | bigint; type SendHandle = net.Socket | net.Server | dgram.Socket | undefined; @@ -109,7 +109,7 @@ declare module "child_process" { * refer to the same value. * * ```js - * const { spawn } = require('node:child_process'); + * import { spawn } from 'node:child_process'; * * const subprocess = spawn('ls'); * @@ -140,7 +140,7 @@ declare module "child_process" { * no IPC channel exists, this property is `undefined`. * @since v7.1.0 */ - readonly channel?: Pipe | null | undefined; + readonly channel?: Control | null; /** * A sparse array of pipes to the child process, corresponding with positions in * the `stdio` option passed to {@link spawn} that have been set @@ -152,9 +152,9 @@ declare module "child_process" { * in the array are `null`. * * ```js - * const assert = require('node:assert'); - * const fs = require('node:fs'); - * const child_process = require('node:child_process'); + * import assert from 'node:assert'; + * import fs from 'node:fs'; + * import child_process from 'node:child_process'; * * const subprocess = child_process.spawn('ls', { * stdio: [ @@ -202,7 +202,7 @@ declare module "child_process" { * emitted. * * ```js - * const { spawn } = require('node:child_process'); + * import { spawn } from 'node:child_process'; * const grep = spawn('grep', ['ssh']); * * console.log(`Spawned child pid: ${grep.pid}`); @@ -249,7 +249,7 @@ declare module "child_process" { * returns `true` if [`kill(2)`](http://man7.org/linux/man-pages/man2/kill.2.html) succeeds, and `false` otherwise. * * ```js - * const { spawn } = require('node:child_process'); + * import { spawn } from 'node:child_process'; * const grep = spawn('grep', ['ssh']); * * grep.on('close', (code, signal) => { @@ -282,7 +282,7 @@ declare module "child_process" { * * ```js * 'use strict'; - * const { spawn } = require('node:child_process'); + * import { spawn } from 'node:child_process'; * * const subprocess = spawn( * 'sh', @@ -320,7 +320,7 @@ declare module "child_process" { * For example, in the parent script: * * ```js - * const cp = require('node:child_process'); + * import cp from 'node:child_process'; * const n = cp.fork(`${__dirname}/sub.js`); * * n.on('message', (m) => { @@ -374,10 +374,12 @@ declare module "child_process" { * a TCP server object to the child process as illustrated in the example below: * * ```js - * const subprocess = require('node:child_process').fork('subprocess.js'); + * import { createServer } from 'node:net'; + * import { fork } from 'node:child_process'; + * const subprocess = fork('subprocess.js'); * * // Open up the server object and send the handle. - * const server = require('node:net').createServer(); + * const server = createServer(); * server.on('connection', (socket) => { * socket.end('handled by parent'); * }); @@ -412,13 +414,14 @@ declare module "child_process" { * handle connections with "normal" or "special" priority: * * ```js - * const { fork } = require('node:child_process'); + * import { createServer } from 'node:net'; + * import { fork } from 'node:child_process'; * const normal = fork('subprocess.js', ['normal']); * const special = fork('subprocess.js', ['special']); * * // Open up the server and send sockets to child. Use pauseOnConnect to prevent * // the sockets from being read before they are sent to the child process. - * const server = require('node:net').createServer({ pauseOnConnect: true }); + * const server = createServer({ pauseOnConnect: true }); * server.on('connection', (socket) => { * * // If this is special priority... @@ -455,7 +458,7 @@ declare module "child_process" { * as the connection may have been closed during the time it takes to send the * connection to the child. * @since v0.5.9 - * @param sendHandle `undefined`, or a [`net.Socket`](https://nodejs.org/docs/latest-v20.x/api/net.html#class-netsocket), [`net.Server`](https://nodejs.org/docs/latest-v20.x/api/net.html#class-netserver), or [`dgram.Socket`](https://nodejs.org/docs/latest-v20.x/api/dgram.html#class-dgramsocket) object. + * @param sendHandle `undefined`, or a [`net.Socket`](https://nodejs.org/docs/latest-v24.x/api/net.html#class-netsocket), [`net.Server`](https://nodejs.org/docs/latest-v24.x/api/net.html#class-netserver), or [`dgram.Socket`](https://nodejs.org/docs/latest-v24.x/api/dgram.html#class-dgramsocket) object. * @param options The `options` argument, if present, is an object used to parameterize the sending of certain types of handles. `options` supports the following properties: */ send(message: Serializable, callback?: (error: Error | null) => void): boolean; @@ -490,7 +493,7 @@ declare module "child_process" { * the child and the parent. * * ```js - * const { spawn } = require('node:child_process'); + * import { spawn } from 'node:child_process'; * * const subprocess = spawn(process.argv[0], ['child_program.js'], { * detached: true, @@ -508,7 +511,7 @@ declare module "child_process" { * to wait for the child to exit before exiting itself. * * ```js - * const { spawn } = require('node:child_process'); + * import { spawn } from 'node:child_process'; * * const subprocess = spawn(process.argv[0], ['child_program.js'], { * detached: true, @@ -610,6 +613,10 @@ declare module "child_process" { Readable | Writable | null | undefined, // extra, no modification ]; } + interface Control extends EventEmitter { + ref(): void; + unref(): void; + } interface MessageOptions { keepOpen?: boolean | undefined; } @@ -711,7 +718,7 @@ declare module "child_process" { * exit code: * * ```js - * const { spawn } = require('node:child_process'); + * import { spawn } from 'node:child_process'; * const ls = spawn('ls', ['-lh', '/usr']); * * ls.stdout.on('data', (data) => { @@ -730,7 +737,7 @@ declare module "child_process" { * Example: A very elaborate way to run `ps ax | grep ssh` * * ```js - * const { spawn } = require('node:child_process'); + * import { spawn } from 'node:child_process'; * const ps = spawn('ps', ['ax']); * const grep = spawn('grep', ['ssh']); * @@ -767,7 +774,7 @@ declare module "child_process" { * Example of checking for failed `spawn`: * * ```js - * const { spawn } = require('node:child_process'); + * import { spawn } from 'node:child_process'; * const subprocess = spawn('bad_command'); * * subprocess.on('error', (err) => { @@ -785,7 +792,7 @@ declare module "child_process" { * the error passed to the callback will be an `AbortError`: * * ```js - * const { spawn } = require('node:child_process'); + * import { spawn } from 'node:child_process'; * const controller = new AbortController(); * const { signal } = controller; * const grep = spawn('grep', ['ssh'], { signal }); @@ -884,18 +891,20 @@ declare module "child_process" { signal?: AbortSignal | undefined; maxBuffer?: number | undefined; killSignal?: NodeJS.Signals | number | undefined; + encoding?: string | null | undefined; } interface ExecOptionsWithStringEncoding extends ExecOptions { - encoding: BufferEncoding; + encoding?: BufferEncoding | undefined; } interface ExecOptionsWithBufferEncoding extends ExecOptions { - encoding: BufferEncoding | null; // specify `null`. + encoding: "buffer" | null; // specify `null`. } + // TODO: Just Plain Wrong™ (see also nodejs/node#57392) interface ExecException extends Error { - cmd?: string | undefined; - killed?: boolean | undefined; - code?: number | undefined; - signal?: NodeJS.Signals | undefined; + cmd?: string; + killed?: boolean; + code?: number; + signal?: NodeJS.Signals; stdout?: string; stderr?: string; } @@ -906,7 +915,7 @@ declare module "child_process" { * need to be dealt with accordingly: * * ```js - * const { exec } = require('node:child_process'); + * import { exec } from 'node:child_process'; * * exec('"/path/to/test file/test.sh" arg1 arg2'); * // Double quotes are used so that the space in the path is not interpreted as @@ -932,7 +941,7 @@ declare module "child_process" { * encoding, `Buffer` objects will be passed to the callback instead. * * ```js - * const { exec } = require('node:child_process'); + * import { exec } from 'node:child_process'; * exec('cat *.js missing_file | wc -l', (error, stdout, stderr) => { * if (error) { * console.error(`exec error: ${error}`); @@ -957,8 +966,9 @@ declare module "child_process" { * callback, but with two additional properties `stdout` and `stderr`. * * ```js - * const util = require('node:util'); - * const exec = util.promisify(require('node:child_process').exec); + * import util from 'node:util'; + * import child_process from 'node:child_process'; + * const exec = util.promisify(child_process.exec); * * async function lsExample() { * const { stdout, stderr } = await exec('ls'); @@ -972,7 +982,7 @@ declare module "child_process" { * the error passed to the callback will be an `AbortError`: * * ```js - * const { exec } = require('node:child_process'); + * import { exec } from 'node:child_process'; * const controller = new AbortController(); * const { signal } = controller; * const child = exec('grep ssh', { signal }, (error) => { @@ -991,39 +1001,24 @@ declare module "child_process" { // `options` with `"buffer"` or `null` for `encoding` means stdout/stderr are definitely `Buffer`. function exec( command: string, - options: { - encoding: "buffer" | null; - } & ExecOptions, - callback?: (error: ExecException | null, stdout: Buffer, stderr: Buffer) => void, + options: ExecOptionsWithBufferEncoding, + callback?: (error: ExecException | null, stdout: NonSharedBuffer, stderr: NonSharedBuffer) => void, ): ChildProcess; - // `options` with well known `encoding` means stdout/stderr are definitely `string`. + // `options` with well-known or absent `encoding` means stdout/stderr are definitely `string`. function exec( command: string, - options: { - encoding: BufferEncoding; - } & ExecOptions, - callback?: (error: ExecException | null, stdout: string, stderr: string) => void, - ): ChildProcess; - // `options` with an `encoding` whose type is `string` means stdout/stderr could either be `Buffer` or `string`. - // There is no guarantee the `encoding` is unknown as `string` is a superset of `BufferEncoding`. - function exec( - command: string, - options: { - encoding: BufferEncoding; - } & ExecOptions, - callback?: (error: ExecException | null, stdout: string | Buffer, stderr: string | Buffer) => void, - ): ChildProcess; - // `options` without an `encoding` means stdout/stderr are definitely `string`. - function exec( - command: string, - options: ExecOptions, + options: ExecOptionsWithStringEncoding, callback?: (error: ExecException | null, stdout: string, stderr: string) => void, ): ChildProcess; // fallback if nothing else matches. Worst case is always `string | Buffer`. function exec( command: string, - options: (ObjectEncodingOptions & ExecOptions) | undefined | null, - callback?: (error: ExecException | null, stdout: string | Buffer, stderr: string | Buffer) => void, + options: ExecOptions | undefined | null, + callback?: ( + error: ExecException | null, + stdout: string | NonSharedBuffer, + stderr: string | NonSharedBuffer, + ) => void, ): ChildProcess; interface PromiseWithChild extends Promise { child: ChildProcess; @@ -1035,35 +1030,24 @@ declare module "child_process" { }>; function __promisify__( command: string, - options: { - encoding: "buffer" | null; - } & ExecOptions, + options: ExecOptionsWithBufferEncoding, ): PromiseWithChild<{ - stdout: Buffer; - stderr: Buffer; + stdout: NonSharedBuffer; + stderr: NonSharedBuffer; }>; function __promisify__( command: string, - options: { - encoding: BufferEncoding; - } & ExecOptions, + options: ExecOptionsWithStringEncoding, ): PromiseWithChild<{ stdout: string; stderr: string; }>; function __promisify__( command: string, - options: ExecOptions, + options: ExecOptions | undefined | null, ): PromiseWithChild<{ - stdout: string; - stderr: string; - }>; - function __promisify__( - command: string, - options?: (ObjectEncodingOptions & ExecOptions) | null, - ): PromiseWithChild<{ - stdout: string | Buffer; - stderr: string | Buffer; + stdout: string | NonSharedBuffer; + stderr: string | NonSharedBuffer; }>; } interface ExecFileOptions extends CommonOptions, Abortable { @@ -1072,20 +1056,21 @@ declare module "child_process" { windowsVerbatimArguments?: boolean | undefined; shell?: boolean | string | undefined; signal?: AbortSignal | undefined; + encoding?: string | null | undefined; } interface ExecFileOptionsWithStringEncoding extends ExecFileOptions { - encoding: BufferEncoding; + encoding?: BufferEncoding | undefined; } interface ExecFileOptionsWithBufferEncoding extends ExecFileOptions { encoding: "buffer" | null; } - interface ExecFileOptionsWithOtherEncoding extends ExecFileOptions { - encoding: BufferEncoding; - } + /** @deprecated Use `ExecFileOptions` instead. */ + interface ExecFileOptionsWithOtherEncoding extends ExecFileOptions {} + // TODO: execFile exceptions can take many forms... this accurately describes none of them type ExecFileException = & Omit & Omit - & { code?: string | number | undefined | null }; + & { code?: string | number | null }; /** * The `child_process.execFile()` function is similar to {@link exec} except that it does not spawn a shell by default. Rather, the specified * executable `file` is spawned directly as a new process making it slightly more @@ -1096,7 +1081,7 @@ declare module "child_process" { * supported. * * ```js - * const { execFile } = require('node:child_process'); + * import { execFile } from 'node:child_process'; * const child = execFile('node', ['--version'], (error, stdout, stderr) => { * if (error) { * throw error; @@ -1119,8 +1104,9 @@ declare module "child_process" { * callback, but with two additional properties `stdout` and `stderr`. * * ```js - * const util = require('node:util'); - * const execFile = util.promisify(require('node:child_process').execFile); + * import util from 'node:util'; + * import child_process from 'node:child_process'; + * const execFile = util.promisify(child_process.execFile); * async function getVersion() { * const { stdout } = await execFile('node', ['--version']); * console.log(stdout); @@ -1136,7 +1122,7 @@ declare module "child_process" { * the error passed to the callback will be an `AbortError`: * * ```js - * const { execFile } = require('node:child_process'); + * import { execFile } from 'node:child_process'; * const controller = new AbortController(); * const { signal } = controller; * const child = execFile('node', ['--version'], { signal }, (error) => { @@ -1149,91 +1135,63 @@ declare module "child_process" { * @param args List of string arguments. * @param callback Called with the output when process terminates. */ - function execFile(file: string): ChildProcess; - function execFile( - file: string, - options: (ObjectEncodingOptions & ExecFileOptions) | undefined | null, - ): ChildProcess; - function execFile(file: string, args?: readonly string[] | null): ChildProcess; - function execFile( - file: string, - args: readonly string[] | undefined | null, - options: (ObjectEncodingOptions & ExecFileOptions) | undefined | null, - ): ChildProcess; // no `options` definitely means stdout/stderr are `string`. function execFile( file: string, - callback: (error: ExecFileException | null, stdout: string, stderr: string) => void, + callback?: (error: ExecFileException | null, stdout: string, stderr: string) => void, ): ChildProcess; function execFile( file: string, args: readonly string[] | undefined | null, - callback: (error: ExecFileException | null, stdout: string, stderr: string) => void, + callback?: (error: ExecFileException | null, stdout: string, stderr: string) => void, ): ChildProcess; // `options` with `"buffer"` or `null` for `encoding` means stdout/stderr are definitely `Buffer`. function execFile( file: string, options: ExecFileOptionsWithBufferEncoding, - callback: (error: ExecFileException | null, stdout: Buffer, stderr: Buffer) => void, + callback?: (error: ExecFileException | null, stdout: NonSharedBuffer, stderr: NonSharedBuffer) => void, ): ChildProcess; function execFile( file: string, args: readonly string[] | undefined | null, options: ExecFileOptionsWithBufferEncoding, - callback: (error: ExecFileException | null, stdout: Buffer, stderr: Buffer) => void, + callback?: (error: ExecFileException | null, stdout: NonSharedBuffer, stderr: NonSharedBuffer) => void, ): ChildProcess; - // `options` with well known `encoding` means stdout/stderr are definitely `string`. + // `options` with well-known or absent `encoding` means stdout/stderr are definitely `string`. function execFile( file: string, options: ExecFileOptionsWithStringEncoding, - callback: (error: ExecFileException | null, stdout: string, stderr: string) => void, + callback?: (error: ExecFileException | null, stdout: string, stderr: string) => void, ): ChildProcess; function execFile( file: string, args: readonly string[] | undefined | null, options: ExecFileOptionsWithStringEncoding, - callback: (error: ExecFileException | null, stdout: string, stderr: string) => void, - ): ChildProcess; - // `options` with an `encoding` whose type is `string` means stdout/stderr could either be `Buffer` or `string`. - // There is no guarantee the `encoding` is unknown as `string` is a superset of `BufferEncoding`. - function execFile( - file: string, - options: ExecFileOptionsWithOtherEncoding, - callback: (error: ExecFileException | null, stdout: string | Buffer, stderr: string | Buffer) => void, - ): ChildProcess; - function execFile( - file: string, - args: readonly string[] | undefined | null, - options: ExecFileOptionsWithOtherEncoding, - callback: (error: ExecFileException | null, stdout: string | Buffer, stderr: string | Buffer) => void, - ): ChildProcess; - // `options` without an `encoding` means stdout/stderr are definitely `string`. - function execFile( - file: string, - options: ExecFileOptions, - callback: (error: ExecFileException | null, stdout: string, stderr: string) => void, - ): ChildProcess; - function execFile( - file: string, - args: readonly string[] | undefined | null, - options: ExecFileOptions, - callback: (error: ExecFileException | null, stdout: string, stderr: string) => void, + callback?: (error: ExecFileException | null, stdout: string, stderr: string) => void, ): ChildProcess; // fallback if nothing else matches. Worst case is always `string | Buffer`. function execFile( file: string, - options: (ObjectEncodingOptions & ExecFileOptions) | undefined | null, + options: ExecFileOptions | undefined | null, callback: - | ((error: ExecFileException | null, stdout: string | Buffer, stderr: string | Buffer) => void) + | (( + error: ExecFileException | null, + stdout: string | NonSharedBuffer, + stderr: string | NonSharedBuffer, + ) => void) | undefined | null, ): ChildProcess; function execFile( file: string, args: readonly string[] | undefined | null, - options: (ObjectEncodingOptions & ExecFileOptions) | undefined | null, + options: ExecFileOptions | undefined | null, callback: - | ((error: ExecFileException | null, stdout: string | Buffer, stderr: string | Buffer) => void) + | (( + error: ExecFileException | null, + stdout: string | NonSharedBuffer, + stderr: string | NonSharedBuffer, + ) => void) | undefined | null, ): ChildProcess; @@ -1253,16 +1211,16 @@ declare module "child_process" { file: string, options: ExecFileOptionsWithBufferEncoding, ): PromiseWithChild<{ - stdout: Buffer; - stderr: Buffer; + stdout: NonSharedBuffer; + stderr: NonSharedBuffer; }>; function __promisify__( file: string, args: readonly string[] | undefined | null, options: ExecFileOptionsWithBufferEncoding, ): PromiseWithChild<{ - stdout: Buffer; - stderr: Buffer; + stdout: NonSharedBuffer; + stderr: NonSharedBuffer; }>; function __promisify__( file: string, @@ -1281,48 +1239,18 @@ declare module "child_process" { }>; function __promisify__( file: string, - options: ExecFileOptionsWithOtherEncoding, + options: ExecFileOptions | undefined | null, ): PromiseWithChild<{ - stdout: string | Buffer; - stderr: string | Buffer; + stdout: string | NonSharedBuffer; + stderr: string | NonSharedBuffer; }>; function __promisify__( file: string, args: readonly string[] | undefined | null, - options: ExecFileOptionsWithOtherEncoding, + options: ExecFileOptions | undefined | null, ): PromiseWithChild<{ - stdout: string | Buffer; - stderr: string | Buffer; - }>; - function __promisify__( - file: string, - options: ExecFileOptions, - ): PromiseWithChild<{ - stdout: string; - stderr: string; - }>; - function __promisify__( - file: string, - args: readonly string[] | undefined | null, - options: ExecFileOptions, - ): PromiseWithChild<{ - stdout: string; - stderr: string; - }>; - function __promisify__( - file: string, - options: (ObjectEncodingOptions & ExecFileOptions) | undefined | null, - ): PromiseWithChild<{ - stdout: string | Buffer; - stderr: string | Buffer; - }>; - function __promisify__( - file: string, - args: readonly string[] | undefined | null, - options: (ObjectEncodingOptions & ExecFileOptions) | undefined | null, - ): PromiseWithChild<{ - stdout: string | Buffer; - stderr: string | Buffer; + stdout: string | NonSharedBuffer; + stderr: string | NonSharedBuffer; }>; } interface ForkOptions extends ProcessEnvOptions, MessagingOptions, Abortable { @@ -1377,7 +1305,7 @@ declare module "child_process" { * console.log(`Hello from ${process.argv[2]}!`); * }, 1_000); * } else { - * const { fork } = require('node:child_process'); + * import { fork } from 'node:child_process'; * const controller = new AbortController(); * const { signal } = controller; * const child = fork(__filename, ['child'], { signal }); @@ -1411,7 +1339,7 @@ declare module "child_process" { stderr: T; status: number | null; signal: NodeJS.Signals | null; - error?: Error | undefined; + error?: Error; } /** * The `child_process.spawnSync()` method is generally identical to {@link spawn} with the exception that the function will not return @@ -1428,11 +1356,11 @@ declare module "child_process" { * @param command The command to run. * @param args List of string arguments. */ - function spawnSync(command: string): SpawnSyncReturns; + function spawnSync(command: string): SpawnSyncReturns; function spawnSync(command: string, options: SpawnSyncOptionsWithStringEncoding): SpawnSyncReturns; - function spawnSync(command: string, options: SpawnSyncOptionsWithBufferEncoding): SpawnSyncReturns; - function spawnSync(command: string, options?: SpawnSyncOptions): SpawnSyncReturns; - function spawnSync(command: string, args: readonly string[]): SpawnSyncReturns; + function spawnSync(command: string, options: SpawnSyncOptionsWithBufferEncoding): SpawnSyncReturns; + function spawnSync(command: string, options?: SpawnSyncOptions): SpawnSyncReturns; + function spawnSync(command: string, args: readonly string[]): SpawnSyncReturns; function spawnSync( command: string, args: readonly string[], @@ -1442,12 +1370,12 @@ declare module "child_process" { command: string, args: readonly string[], options: SpawnSyncOptionsWithBufferEncoding, - ): SpawnSyncReturns; + ): SpawnSyncReturns; function spawnSync( command: string, args?: readonly string[], options?: SpawnSyncOptions, - ): SpawnSyncReturns; + ): SpawnSyncReturns; interface CommonExecOptions extends CommonOptions { input?: string | NodeJS.ArrayBufferView | undefined; /** @@ -1489,10 +1417,10 @@ declare module "child_process" { * @param command The command to run. * @return The stdout from the command. */ - function execSync(command: string): Buffer; + function execSync(command: string): NonSharedBuffer; function execSync(command: string, options: ExecSyncOptionsWithStringEncoding): string; - function execSync(command: string, options: ExecSyncOptionsWithBufferEncoding): Buffer; - function execSync(command: string, options?: ExecSyncOptions): string | Buffer; + function execSync(command: string, options: ExecSyncOptionsWithBufferEncoding): NonSharedBuffer; + function execSync(command: string, options?: ExecSyncOptions): string | NonSharedBuffer; interface ExecFileSyncOptions extends CommonExecOptions { shell?: boolean | string | undefined; } @@ -1500,7 +1428,7 @@ declare module "child_process" { encoding: BufferEncoding; } interface ExecFileSyncOptionsWithBufferEncoding extends ExecFileSyncOptions { - encoding?: "buffer" | null; // specify `null`. + encoding?: "buffer" | null | undefined; // specify `null`. } /** * The `child_process.execFileSync()` method is generally identical to {@link execFile} with the exception that the method will not @@ -1522,11 +1450,11 @@ declare module "child_process" { * @param args List of string arguments. * @return The stdout from the command. */ - function execFileSync(file: string): Buffer; + function execFileSync(file: string): NonSharedBuffer; function execFileSync(file: string, options: ExecFileSyncOptionsWithStringEncoding): string; - function execFileSync(file: string, options: ExecFileSyncOptionsWithBufferEncoding): Buffer; - function execFileSync(file: string, options?: ExecFileSyncOptions): string | Buffer; - function execFileSync(file: string, args: readonly string[]): Buffer; + function execFileSync(file: string, options: ExecFileSyncOptionsWithBufferEncoding): NonSharedBuffer; + function execFileSync(file: string, options?: ExecFileSyncOptions): string | NonSharedBuffer; + function execFileSync(file: string, args: readonly string[]): NonSharedBuffer; function execFileSync( file: string, args: readonly string[], @@ -1536,8 +1464,12 @@ declare module "child_process" { file: string, args: readonly string[], options: ExecFileSyncOptionsWithBufferEncoding, - ): Buffer; - function execFileSync(file: string, args?: readonly string[], options?: ExecFileSyncOptions): string | Buffer; + ): NonSharedBuffer; + function execFileSync( + file: string, + args?: readonly string[], + options?: ExecFileSyncOptions, + ): string | NonSharedBuffer; } declare module "node:child_process" { export * from "child_process"; diff --git a/backend/node_modules/@types/node/cluster.d.ts b/backend/node_modules/@types/node/cluster.d.ts index 7711927..cdbc219 100644 --- a/backend/node_modules/@types/node/cluster.d.ts +++ b/backend/node_modules/@types/node/cluster.d.ts @@ -1,7 +1,7 @@ /** * Clusters of Node.js processes can be used to run multiple instances of Node.js * that can distribute workloads among their application threads. When process isolation - * is not needed, use the [`worker_threads`](https://nodejs.org/docs/latest-v20.x/api/worker_threads.html) + * is not needed, use the [`worker_threads`](https://nodejs.org/docs/latest-v24.x/api/worker_threads.html) * module instead, which allows running multiple application threads within a single Node.js instance. * * The cluster module allows easy creation of child processes that all share @@ -50,7 +50,7 @@ * ``` * * On Windows, it is not yet possible to set up a named pipe server in a worker. - * @see [source](https://github.com/nodejs/node/blob/v20.13.1/lib/cluster.js) + * @see [source](https://github.com/nodejs/node/blob/v24.x/lib/cluster.js) */ declare module "cluster" { import * as child from "node:child_process"; @@ -72,7 +72,7 @@ declare module "cluster" { * String arguments passed to worker. * @default process.argv.slice(2) */ - args?: string[] | undefined; + args?: readonly string[] | undefined; /** * Whether or not to send output to parent's stdio. * @default false @@ -80,8 +80,8 @@ declare module "cluster" { silent?: boolean | undefined; /** * Configures the stdio of forked processes. Because the cluster module relies on IPC to function, this configuration must - * contain an `'ipc'` entry. When this option is provided, it overrides `silent`. See [`child_prcess.spawn()`](https://nodejs.org/docs/latest-v20.x/api/child_process.html#child_processspawncommand-args-options)'s - * [`stdio`](https://nodejs.org/docs/latest-v20.x/api/child_process.html#optionsstdio). + * contain an `'ipc'` entry. When this option is provided, it overrides `silent`. See [`child_prcess.spawn()`](https://nodejs.org/docs/latest-v24.x/api/child_process.html#child_processspawncommand-args-options)'s + * [`stdio`](https://nodejs.org/docs/latest-v24.x/api/child_process.html#optionsstdio). */ stdio?: any[] | undefined; /** @@ -99,7 +99,7 @@ declare module "cluster" { inspectPort?: number | (() => number) | undefined; /** * Specify the kind of serialization used for sending messages between processes. Possible values are `'json'` and `'advanced'`. - * See [Advanced serialization for `child_process`](https://nodejs.org/docs/latest-v20.x/api/child_process.html#advanced-serialization) for more details. + * See [Advanced serialization for `child_process`](https://nodejs.org/docs/latest-v24.x/api/child_process.html#advanced-serialization) for more details. * @default false */ serialization?: SerializationType | undefined; @@ -142,10 +142,10 @@ declare module "cluster" { */ id: number; /** - * All workers are created using [`child_process.fork()`](https://nodejs.org/docs/latest-v20.x/api/child_process.html#child_processforkmodulepath-args-options), the returned object + * All workers are created using [`child_process.fork()`](https://nodejs.org/docs/latest-v24.x/api/child_process.html#child_processforkmodulepath-args-options), the returned object * from this function is stored as `.process`. In a worker, the global `process` is stored. * - * See: [Child Process module](https://nodejs.org/docs/latest-v20.x/api/child_process.html#child_processforkmodulepath-args-options). + * See: [Child Process module](https://nodejs.org/docs/latest-v24.x/api/child_process.html#child_processforkmodulepath-args-options). * * Workers will call `process.exit(0)` if the `'disconnect'` event occurs * on `process` and `.exitedAfterDisconnect` is not `true`. This protects against @@ -156,7 +156,7 @@ declare module "cluster" { /** * Send a message to a worker or primary, optionally with a handle. * - * In the primary, this sends a message to a specific worker. It is identical to [`ChildProcess.send()`](https://nodejs.org/docs/latest-v20.x/api/child_process.html#subprocesssendmessage-sendhandle-options-callback). + * In the primary, this sends a message to a specific worker. It is identical to [`ChildProcess.send()`](https://nodejs.org/docs/latest-v24.x/api/child_process.html#subprocesssendmessage-sendhandle-options-callback). * * In a worker, this sends a message to the primary. It is identical to `process.send()`. * @@ -198,7 +198,7 @@ declare module "cluster" { * This method is aliased as `worker.destroy()` for backwards compatibility. * * In a worker, `process.kill()` exists, but it is not this function; - * it is [`kill()`](https://nodejs.org/docs/latest-v20.x/api/process.html#processkillpid-signal). + * it is [`kill()`](https://nodejs.org/docs/latest-v24.x/api/process.html#processkillpid-signal). * @since v0.9.12 * @param [signal='SIGTERM'] Name of the kill signal to send to the worker process. */ @@ -231,6 +231,8 @@ declare module "cluster" { * the `'disconnect'` event has not been emitted after some time. * * ```js + * import net from 'node:net'; + * * if (cluster.isPrimary) { * const worker = cluster.fork(); * let timeout; @@ -248,7 +250,6 @@ declare module "cluster" { * }); * * } else if (cluster.isWorker) { - * const net = require('node:net'); * const server = net.createServer((socket) => { * // Connections never end * }); @@ -265,7 +266,7 @@ declare module "cluster" { * @since v0.7.7 * @return A reference to `worker`. */ - disconnect(): void; + disconnect(): this; /** * This function returns `true` if the worker is connected to its primary via its * IPC channel, `false` otherwise. A worker is connected to its primary after it @@ -411,7 +412,7 @@ declare module "cluster" { readonly isWorker: boolean; /** * The scheduling policy, either `cluster.SCHED_RR` for round-robin or `cluster.SCHED_NONE` to leave it to the operating system. This is a - * global setting and effectively frozen once either the first worker is spawned, or [`.setupPrimary()`](https://nodejs.org/docs/latest-v20.x/api/cluster.html#clustersetupprimarysettings) + * global setting and effectively frozen once either the first worker is spawned, or [`.setupPrimary()`](https://nodejs.org/docs/latest-v24.x/api/cluster.html#clustersetupprimarysettings) * is called, whichever comes first. * * `SCHED_RR` is the default on all operating systems except Windows. Windows will change to `SCHED_RR` once libuv is able to effectively distribute @@ -422,24 +423,24 @@ declare module "cluster" { */ schedulingPolicy: number; /** - * After calling [`.setupPrimary()`](https://nodejs.org/docs/latest-v20.x/api/cluster.html#clustersetupprimarysettings) - * (or [`.fork()`](https://nodejs.org/docs/latest-v20.x/api/cluster.html#clusterforkenv)) this settings object will contain + * After calling [`.setupPrimary()`](https://nodejs.org/docs/latest-v24.x/api/cluster.html#clustersetupprimarysettings) + * (or [`.fork()`](https://nodejs.org/docs/latest-v24.x/api/cluster.html#clusterforkenv)) this settings object will contain * the settings, including the default values. * * This object is not intended to be changed or set manually. * @since v0.7.1 */ readonly settings: ClusterSettings; - /** @deprecated since v16.0.0 - use [`.setupPrimary()`](https://nodejs.org/docs/latest-v20.x/api/cluster.html#clustersetupprimarysettings) instead. */ + /** @deprecated since v16.0.0 - use [`.setupPrimary()`](https://nodejs.org/docs/latest-v24.x/api/cluster.html#clustersetupprimarysettings) instead. */ setupMaster(settings?: ClusterSettings): void; /** * `setupPrimary` is used to change the default 'fork' behavior. Once called, the settings will be present in `cluster.settings`. * - * Any settings changes only affect future calls to [`.fork()`](https://nodejs.org/docs/latest-v20.x/api/cluster.html#clusterforkenv) + * Any settings changes only affect future calls to [`.fork()`](https://nodejs.org/docs/latest-v24.x/api/cluster.html#clusterforkenv) * and have no effect on workers that are already running. * * The only attribute of a worker that cannot be set via `.setupPrimary()` is the `env` passed to - * [`.fork()`](https://nodejs.org/docs/latest-v20.x/api/cluster.html#clusterforkenv). + * [`.fork()`](https://nodejs.org/docs/latest-v24.x/api/cluster.html#clusterforkenv). * * The defaults above apply to the first call only; the defaults for later calls are the current values at the time of * `cluster.setupPrimary()` is called. @@ -480,7 +481,7 @@ declare module "cluster" { * ``` * @since v0.7.0 */ - readonly worker?: Worker | undefined; + readonly worker?: Worker; /** * A hash that stores the active worker objects, keyed by `id` field. This makes it easy to loop through all the workers. It is only available in the primary process. * @@ -496,7 +497,7 @@ declare module "cluster" { * ``` * @since v0.7.0 */ - readonly workers?: NodeJS.Dict | undefined; + readonly workers?: NodeJS.Dict; readonly SCHED_NONE: number; readonly SCHED_RR: number; /** @@ -549,10 +550,9 @@ declare module "cluster" { prependListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this; prependListener(event: "fork", listener: (worker: Worker) => void): this; prependListener(event: "listening", listener: (worker: Worker, address: Address) => void): this; - // the handle is a net.Socket or net.Server object, or undefined. prependListener( event: "message", - listener: (worker: Worker, message: any, handle?: net.Socket | net.Server) => void, + listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void, ): this; prependListener(event: "online", listener: (worker: Worker) => void): this; prependListener(event: "setup", listener: (settings: ClusterSettings) => void): this; diff --git a/backend/node_modules/@types/node/console.d.ts b/backend/node_modules/@types/node/console.d.ts index 3d1a6c2..3c8a682 100644 --- a/backend/node_modules/@types/node/console.d.ts +++ b/backend/node_modules/@types/node/console.d.ts @@ -5,12 +5,12 @@ * The module exports two specific components: * * * A `Console` class with methods such as `console.log()`, `console.error()`, and `console.warn()` that can be used to write to any Node.js stream. - * * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and - * [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without calling `require('node:console')`. + * * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v24.x/api/process.html#processstdout) and + * [`process.stderr`](https://nodejs.org/docs/latest-v24.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. * * _**Warning**_: The global console object's methods are neither consistently * synchronous like the browser APIs they resemble, nor are they consistently - * asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for + * asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v24.x/api/process.html#a-note-on-process-io) for * more information. * * Example using the global `console`: @@ -54,7 +54,7 @@ * myConsole.warn(`Danger ${name}! Danger!`); * // Prints: Danger Will Robinson! Danger!, to err * ``` - * @see [source](https://github.com/nodejs/node/blob/v20.13.1/lib/console.js) + * @see [source](https://github.com/nodejs/node/blob/v24.x/lib/console.js) */ declare module "console" { import console = require("node:console"); @@ -70,7 +70,7 @@ declare module "node:console" { * `console.assert()` writes a message if `value` is [falsy](https://developer.mozilla.org/en-US/docs/Glossary/Falsy) or omitted. It only * writes a message and does not otherwise affect execution. The output always * starts with `"Assertion failed"`. If provided, `message` is formatted using - * [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args). + * [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args). * * If `value` is [truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy), nothing happens. * @@ -152,7 +152,7 @@ declare module "node:console" { */ debug(message?: any, ...optionalParams: any[]): void; /** - * Uses [`util.inspect()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilinspectobject-options) on `obj` and prints the resulting string to `stdout`. + * Uses [`util.inspect()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilinspectobject-options) on `obj` and prints the resulting string to `stdout`. * This function bypasses any custom `inspect()` function defined on `obj`. * @since v0.1.101 */ @@ -167,7 +167,7 @@ declare module "node:console" { * Prints to `stderr` with newline. Multiple arguments can be passed, with the * first used as the primary message and all additional used as substitution * values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) - * (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). + * (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args)). * * ```js * const code = 5; @@ -178,8 +178,8 @@ declare module "node:console" { * ``` * * If formatting elements (e.g. `%d`) are not found in the first string then - * [`util.inspect()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilinspectobject-options) is called on each argument and the - * resulting string values are concatenated. See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) + * [`util.inspect()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilinspectobject-options) is called on each argument and the + * resulting string values are concatenated. See [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args) * for more information. * @since v0.1.100 */ @@ -211,7 +211,7 @@ declare module "node:console" { * Prints to `stdout` with newline. Multiple arguments can be passed, with the * first used as the primary message and all additional used as substitution * values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) - * (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). + * (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args)). * * ```js * const count = 5; @@ -221,7 +221,7 @@ declare module "node:console" { * // Prints: count: 5, to stdout * ``` * - * See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information. + * See [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args) for more information. * @since v0.1.100 */ log(message?: any, ...optionalParams: any[]): void; @@ -297,7 +297,7 @@ declare module "node:console" { */ timeLog(label?: string, ...data: any[]): void; /** - * Prints to `stderr` the string `'Trace: '`, followed by the [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) + * Prints to `stderr` the string `'Trace: '`, followed by the [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args) * formatted message and stack trace to the current position in the code. * * ```js @@ -361,12 +361,12 @@ declare module "node:console" { * The module exports two specific components: * * * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. - * * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and - * [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without calling `require('console')`. + * * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v24.x/api/process.html#processstdout) and + * [`process.stderr`](https://nodejs.org/docs/latest-v24.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. * * _**Warning**_: The global console object's methods are neither consistently * synchronous like the browser APIs they resemble, nor are they consistently - * asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for + * asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v24.x/api/process.html#a-note-on-process-io) for * more information. * * Example using the global `console`: @@ -410,7 +410,7 @@ declare module "node:console" { * myConsole.warn(`Danger ${name}! Danger!`); * // Prints: Danger Will Robinson! Danger!, to err * ``` - * @see [source](https://github.com/nodejs/node/blob/v20.11.1/lib/console.js) + * @see [source](https://github.com/nodejs/node/blob/v24.x/lib/console.js) */ namespace console { interface ConsoleConstructorOptions { @@ -431,9 +431,10 @@ declare module "node:console" { colorMode?: boolean | "auto" | undefined; /** * Specifies options that are passed along to - * [`util.inspect()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilinspectobject-options). + * `util.inspect()`. Can be an options object or, if different options + * for stdout and stderr are desired, a `Map` from stream objects to options. */ - inspectOptions?: InspectOptions | undefined; + inspectOptions?: InspectOptions | ReadonlyMap | undefined; /** * Set group indentation. * @default 2 diff --git a/backend/node_modules/@types/node/constants.d.ts b/backend/node_modules/@types/node/constants.d.ts index c3ac2b8..5685a9d 100644 --- a/backend/node_modules/@types/node/constants.d.ts +++ b/backend/node_modules/@types/node/constants.d.ts @@ -1,16 +1,18 @@ -/** @deprecated since v6.3.0 - use constants property exposed by the relevant module instead. */ +/** + * @deprecated The `node:constants` module is deprecated. When requiring access to constants + * relevant to specific Node.js builtin modules, developers should instead refer + * to the `constants` property exposed by the relevant module. For instance, + * `require('node:fs').constants` and `require('node:os').constants`. + */ declare module "constants" { - import { constants as osConstants, SignalConstants } from "node:os"; - import { constants as cryptoConstants } from "node:crypto"; - import { constants as fsConstants } from "node:fs"; - - const exp: - & typeof osConstants.errno - & typeof osConstants.priority - & SignalConstants - & typeof cryptoConstants - & typeof fsConstants; - export = exp; + const constants: + & typeof import("node:os").constants.dlopen + & typeof import("node:os").constants.errno + & typeof import("node:os").constants.priority + & typeof import("node:os").constants.signals + & typeof import("node:fs").constants + & typeof import("node:crypto").constants; + export = constants; } declare module "node:constants" { diff --git a/backend/node_modules/@types/node/crypto.d.ts b/backend/node_modules/@types/node/crypto.d.ts index 10683ed..d975caf 100644 --- a/backend/node_modules/@types/node/crypto.d.ts +++ b/backend/node_modules/@types/node/crypto.d.ts @@ -14,9 +14,10 @@ * // Prints: * // c0fa1bc00531bd78ef38c628449c5102aeabd49b5dc3a2a516ea6ea959d6658e * ``` - * @see [source](https://github.com/nodejs/node/blob/v20.13.1/lib/crypto.js) + * @see [source](https://github.com/nodejs/node/blob/v24.x/lib/crypto.js) */ declare module "crypto" { + import { NonSharedBuffer } from "node:buffer"; import * as stream from "node:stream"; import { PeerCertificate } from "node:tls"; /** @@ -44,7 +45,7 @@ declare module "crypto" { * @param encoding The `encoding` of the `spkac` string. * @return The challenge component of the `spkac` data structure, which includes a public key and a challenge. */ - static exportChallenge(spkac: BinaryLike): Buffer; + static exportChallenge(spkac: BinaryLike): NonSharedBuffer; /** * ```js * const { Certificate } = await import('node:crypto'); @@ -57,7 +58,7 @@ declare module "crypto" { * @param encoding The `encoding` of the `spkac` string. * @return The public key component of the `spkac` data structure, which includes a public key and a challenge. */ - static exportPublicKey(spkac: BinaryLike, encoding?: string): Buffer; + static exportPublicKey(spkac: BinaryLike, encoding?: string): NonSharedBuffer; /** * ```js * import { Buffer } from 'node:buffer'; @@ -78,7 +79,7 @@ declare module "crypto" { * @returns The challenge component of the `spkac` data structure, * which includes a public key and a challenge. */ - exportChallenge(spkac: BinaryLike): Buffer; + exportChallenge(spkac: BinaryLike): NonSharedBuffer; /** * @deprecated * @param spkac @@ -86,7 +87,7 @@ declare module "crypto" { * @returns The public key component of the `spkac` data structure, * which includes a public key and a challenge. */ - exportPublicKey(spkac: BinaryLike, encoding?: string): Buffer; + exportPublicKey(spkac: BinaryLike, encoding?: string): NonSharedBuffer; /** * @deprecated * @param spkac @@ -96,7 +97,7 @@ declare module "crypto" { verifySpkac(spkac: NodeJS.ArrayBufferView): boolean; } namespace constants { - // https://nodejs.org/dist/latest-v20.x/docs/api/crypto.html#crypto-constants + // https://nodejs.org/dist/latest-v24.x/docs/api/crypto.html#crypto-constants const OPENSSL_VERSION_NUMBER: number; /** Applies multiple bug workarounds within OpenSSL. See https://www.openssl.org/docs/man1.0.2/ssl/SSL_CTX_set_options.html for detail. */ const SSL_OP_ALL: number; @@ -402,7 +403,7 @@ declare module "crypto" { * @since v0.1.92 * @param encoding The `encoding` of the return value. */ - digest(): Buffer; + digest(): NonSharedBuffer; digest(encoding: BinaryToTextEncoding): string; } /** @@ -496,7 +497,7 @@ declare module "crypto" { * @since v0.1.94 * @param encoding The `encoding` of the return value. */ - digest(): Buffer; + digest(): NonSharedBuffer; digest(encoding: BinaryToTextEncoding): string; } type KeyObjectType = "secret" | "public" | "private"; @@ -510,50 +511,50 @@ declare module "crypto" { format: "jwk"; } interface JsonWebKey { - crv?: string | undefined; - d?: string | undefined; - dp?: string | undefined; - dq?: string | undefined; - e?: string | undefined; - k?: string | undefined; - kty?: string | undefined; - n?: string | undefined; - p?: string | undefined; - q?: string | undefined; - qi?: string | undefined; - x?: string | undefined; - y?: string | undefined; + crv?: string; + d?: string; + dp?: string; + dq?: string; + e?: string; + k?: string; + kty?: string; + n?: string; + p?: string; + q?: string; + qi?: string; + x?: string; + y?: string; [key: string]: unknown; } interface AsymmetricKeyDetails { /** * Key size in bits (RSA, DSA). */ - modulusLength?: number | undefined; + modulusLength?: number; /** * Public exponent (RSA). */ - publicExponent?: bigint | undefined; + publicExponent?: bigint; /** * Name of the message digest (RSA-PSS). */ - hashAlgorithm?: string | undefined; + hashAlgorithm?: string; /** * Name of the message digest used by MGF1 (RSA-PSS). */ - mgf1HashAlgorithm?: string | undefined; + mgf1HashAlgorithm?: string; /** * Minimal salt length in bytes (RSA-PSS). */ - saltLength?: number | undefined; + saltLength?: number; /** * Size of q in bits (DSA). */ - divisorLength?: number | undefined; + divisorLength?: number; /** * Name of the curve (EC). */ - namedCurve?: string | undefined; + namedCurve?: string; } /** * Node.js uses a `KeyObject` class to represent a symmetric or asymmetric key, @@ -591,29 +592,14 @@ declare module "crypto" { */ static from(key: webcrypto.CryptoKey): KeyObject; /** - * For asymmetric keys, this property represents the type of the key. Supported key - * types are: - * - * * `'rsa'` (OID 1.2.840.113549.1.1.1) - * * `'rsa-pss'` (OID 1.2.840.113549.1.1.10) - * * `'dsa'` (OID 1.2.840.10040.4.1) - * * `'ec'` (OID 1.2.840.10045.2.1) - * * `'x25519'` (OID 1.3.101.110) - * * `'x448'` (OID 1.3.101.111) - * * `'ed25519'` (OID 1.3.101.112) - * * `'ed448'` (OID 1.3.101.113) - * * `'dh'` (OID 1.2.840.113549.1.3.1) + * For asymmetric keys, this property represents the type of the key. See the + * supported [asymmetric key types](https://nodejs.org/docs/latest-v24.x/api/crypto.html#asymmetric-key-types). * * This property is `undefined` for unrecognized `KeyObject` types and symmetric * keys. * @since v11.6.0 */ - asymmetricKeyType?: KeyType | undefined; - /** - * For asymmetric keys, this property represents the size of the embedded key in - * bytes. This property is `undefined` for symmetric keys. - */ - asymmetricKeySize?: number | undefined; + asymmetricKeyType?: KeyType; /** * This property exists only on asymmetric keys. Depending on the type of the key, * this object contains information about the key. None of the information obtained @@ -627,7 +613,7 @@ declare module "crypto" { * Other key details might be exposed via this API using additional attributes. * @since v15.7.0 */ - asymmetricKeyDetails?: AsymmetricKeyDetails | undefined; + asymmetricKeyDetails?: AsymmetricKeyDetails; /** * For symmetric keys, the following encoding options can be used: * @@ -651,8 +637,8 @@ declare module "crypto" { * PKCS#1 and SEC1 encryption. * @since v11.6.0 */ - export(options: KeyExportOptions<"pem">): string | Buffer; - export(options?: KeyExportOptions<"der">): Buffer; + export(options: KeyExportOptions<"pem">): string | NonSharedBuffer; + export(options?: KeyExportOptions<"der">): NonSharedBuffer; export(options?: JwkKeyExportOptions): JsonWebKey; /** * Returns `true` or `false` depending on whether the keys have exactly the same @@ -666,7 +652,20 @@ declare module "crypto" { * property is `undefined` for asymmetric keys. * @since v11.6.0 */ - symmetricKeySize?: number | undefined; + symmetricKeySize?: number; + /** + * Converts a `KeyObject` instance to a `CryptoKey`. + * @since 22.10.0 + */ + toCryptoKey( + algorithm: + | webcrypto.AlgorithmIdentifier + | webcrypto.RsaHashedImportParams + | webcrypto.EcKeyImportParams + | webcrypto.HmacImportParams, + extractable: boolean, + keyUsages: readonly webcrypto.KeyUsage[], + ): webcrypto.CryptoKey; /** * Depending on the type of this `KeyObject`, this property is either`'secret'` for secret (symmetric) keys, `'public'` for public (asymmetric) keys * or `'private'` for private (asymmetric) keys. @@ -674,9 +673,10 @@ declare module "crypto" { */ type: KeyObjectType; } - type CipherCCMTypes = "aes-128-ccm" | "aes-192-ccm" | "aes-256-ccm" | "chacha20-poly1305"; + type CipherCCMTypes = "aes-128-ccm" | "aes-192-ccm" | "aes-256-ccm"; type CipherGCMTypes = "aes-128-gcm" | "aes-192-gcm" | "aes-256-gcm"; type CipherOCBTypes = "aes-128-ocb" | "aes-192-ocb" | "aes-256-ocb"; + type CipherChaCha20Poly1305Types = "chacha20-poly1305"; type BinaryLike = string | NodeJS.ArrayBufferView; type CipherKey = BinaryLike | KeyObject; interface CipherCCMOptions extends stream.TransformOptions { @@ -688,48 +688,10 @@ declare module "crypto" { interface CipherOCBOptions extends stream.TransformOptions { authTagLength: number; } - /** - * Creates and returns a `Cipher` object that uses the given `algorithm` and `password`. - * - * The `options` argument controls stream behavior and is optional except when a - * cipher in CCM or OCB mode (e.g. `'aes-128-ccm'`) is used. In that case, the`authTagLength` option is required and specifies the length of the - * authentication tag in bytes, see `CCM mode`. In GCM mode, the `authTagLength`option is not required but can be used to set the length of the authentication - * tag that will be returned by `getAuthTag()` and defaults to 16 bytes. - * For `chacha20-poly1305`, the `authTagLength` option defaults to 16 bytes. - * - * The `algorithm` is dependent on OpenSSL, examples are `'aes192'`, etc. On - * recent OpenSSL releases, `openssl list -cipher-algorithms` will - * display the available cipher algorithms. - * - * The `password` is used to derive the cipher key and initialization vector (IV). - * The value must be either a `'latin1'` encoded string, a `Buffer`, a`TypedArray`, or a `DataView`. - * - * **This function is semantically insecure for all** - * **supported ciphers and fatally flawed for ciphers in counter mode (such as CTR,** - * **GCM, or CCM).** - * - * The implementation of `crypto.createCipher()` derives keys using the OpenSSL - * function [`EVP_BytesToKey`](https://www.openssl.org/docs/man3.0/man3/EVP_BytesToKey.html) with the digest algorithm set to MD5, one - * iteration, and no salt. The lack of salt allows dictionary attacks as the same - * password always creates the same key. The low iteration count and - * non-cryptographically secure hash algorithm allow passwords to be tested very - * rapidly. - * - * In line with OpenSSL's recommendation to use a more modern algorithm instead of [`EVP_BytesToKey`](https://www.openssl.org/docs/man3.0/man3/EVP_BytesToKey.html) it is recommended that - * developers derive a key and IV on - * their own using {@link scrypt} and to use {@link createCipheriv} to create the `Cipher` object. Users should not use ciphers with counter mode - * (e.g. CTR, GCM, or CCM) in `crypto.createCipher()`. A warning is emitted when - * they are used in order to avoid the risk of IV reuse that causes - * vulnerabilities. For the case when IV is reused in GCM, see [Nonce-Disrespecting Adversaries](https://github.com/nonce-disrespect/nonce-disrespect) for details. - * @since v0.1.94 - * @deprecated Since v10.0.0 - Use {@link createCipheriv} instead. - * @param options `stream.transform` options - */ - function createCipher(algorithm: CipherCCMTypes, password: BinaryLike, options: CipherCCMOptions): CipherCCM; - /** @deprecated since v10.0.0 use `createCipheriv()` */ - function createCipher(algorithm: CipherGCMTypes, password: BinaryLike, options?: CipherGCMOptions): CipherGCM; - /** @deprecated since v10.0.0 use `createCipheriv()` */ - function createCipher(algorithm: string, password: BinaryLike, options?: stream.TransformOptions): Cipher; + interface CipherChaCha20Poly1305Options extends stream.TransformOptions { + /** @default 16 */ + authTagLength?: number | undefined; + } /** * Creates and returns a `Cipher` object, with the given `algorithm`, `key` and * initialization vector (`iv`). @@ -778,14 +740,20 @@ declare module "crypto" { iv: BinaryLike, options?: CipherGCMOptions, ): CipherGCM; + function createCipheriv( + algorithm: CipherChaCha20Poly1305Types, + key: CipherKey, + iv: BinaryLike, + options?: CipherChaCha20Poly1305Options, + ): CipherChaCha20Poly1305; function createCipheriv( algorithm: string, key: CipherKey, iv: BinaryLike | null, options?: stream.TransformOptions, - ): Cipher; + ): Cipheriv; /** - * Instances of the `Cipher` class are used to encrypt data. The class can be + * Instances of the `Cipheriv` class are used to encrypt data. The class can be * used in one of two ways: * * * As a `stream` that is both readable and writable, where plain unencrypted @@ -793,11 +761,11 @@ declare module "crypto" { * * Using the `cipher.update()` and `cipher.final()` methods to produce * the encrypted data. * - * The {@link createCipher} or {@link createCipheriv} methods are - * used to create `Cipher` instances. `Cipher` objects are not to be created + * The {@link createCipheriv} method is + * used to create `Cipheriv` instances. `Cipheriv` objects are not to be created * directly using the `new` keyword. * - * Example: Using `Cipher` objects as streams: + * Example: Using `Cipheriv` objects as streams: * * ```js * const { @@ -832,7 +800,7 @@ declare module "crypto" { * }); * ``` * - * Example: Using `Cipher` and piped streams: + * Example: Using `Cipheriv` and piped streams: * * ```js * import { @@ -903,7 +871,7 @@ declare module "crypto" { * ``` * @since v0.1.94 */ - class Cipher extends stream.Transform { + class Cipheriv extends stream.Transform { private constructor(); /** * Updates the cipher with `data`. If the `inputEncoding` argument is given, @@ -919,22 +887,22 @@ declare module "crypto" { * @param inputEncoding The `encoding` of the data. * @param outputEncoding The `encoding` of the return value. */ - update(data: BinaryLike): Buffer; - update(data: string, inputEncoding: Encoding): Buffer; + update(data: BinaryLike): NonSharedBuffer; + update(data: string, inputEncoding: Encoding): NonSharedBuffer; update(data: NodeJS.ArrayBufferView, inputEncoding: undefined, outputEncoding: Encoding): string; update(data: string, inputEncoding: Encoding | undefined, outputEncoding: Encoding): string; /** - * Once the `cipher.final()` method has been called, the `Cipher` object can no + * Once the `cipher.final()` method has been called, the `Cipheriv` object can no * longer be used to encrypt data. Attempts to call `cipher.final()` more than * once will result in an error being thrown. * @since v0.1.94 * @param outputEncoding The `encoding` of the return value. * @return Any remaining enciphered contents. If `outputEncoding` is specified, a string is returned. If an `outputEncoding` is not provided, a {@link Buffer} is returned. */ - final(): Buffer; + final(): NonSharedBuffer; final(outputEncoding: BufferEncoding): string; /** - * When using block encryption algorithms, the `Cipher` class will automatically + * When using block encryption algorithms, the `Cipheriv` class will automatically * add padding to the input data to the appropriate block size. To disable the * default padding call `cipher.setAutoPadding(false)`. * @@ -950,66 +918,44 @@ declare module "crypto" { */ setAutoPadding(autoPadding?: boolean): this; } - interface CipherCCM extends Cipher { + interface CipherCCM extends Cipheriv { setAAD( buffer: NodeJS.ArrayBufferView, options: { plaintextLength: number; }, ): this; - getAuthTag(): Buffer; + getAuthTag(): NonSharedBuffer; } - interface CipherGCM extends Cipher { + interface CipherGCM extends Cipheriv { setAAD( buffer: NodeJS.ArrayBufferView, options?: { plaintextLength: number; }, ): this; - getAuthTag(): Buffer; + getAuthTag(): NonSharedBuffer; } - interface CipherOCB extends Cipher { + interface CipherOCB extends Cipheriv { setAAD( buffer: NodeJS.ArrayBufferView, options?: { plaintextLength: number; }, ): this; - getAuthTag(): Buffer; + getAuthTag(): NonSharedBuffer; + } + interface CipherChaCha20Poly1305 extends Cipheriv { + setAAD( + buffer: NodeJS.ArrayBufferView, + options: { + plaintextLength: number; + }, + ): this; + getAuthTag(): NonSharedBuffer; } /** - * Creates and returns a `Decipher` object that uses the given `algorithm` and `password` (key). - * - * The `options` argument controls stream behavior and is optional except when a - * cipher in CCM or OCB mode (e.g. `'aes-128-ccm'`) is used. In that case, the `authTagLength` option is required and specifies the length of the - * authentication tag in bytes, see `CCM mode`. - * For `chacha20-poly1305`, the `authTagLength` option defaults to 16 bytes. - * - * **This function is semantically insecure for all** - * **supported ciphers and fatally flawed for ciphers in counter mode (such as CTR,** - * **GCM, or CCM).** - * - * The implementation of `crypto.createDecipher()` derives keys using the OpenSSL - * function [`EVP_BytesToKey`](https://www.openssl.org/docs/man3.0/man3/EVP_BytesToKey.html) with the digest algorithm set to MD5, one - * iteration, and no salt. The lack of salt allows dictionary attacks as the same - * password always creates the same key. The low iteration count and - * non-cryptographically secure hash algorithm allow passwords to be tested very - * rapidly. - * - * In line with OpenSSL's recommendation to use a more modern algorithm instead of [`EVP_BytesToKey`](https://www.openssl.org/docs/man3.0/man3/EVP_BytesToKey.html) it is recommended that - * developers derive a key and IV on - * their own using {@link scrypt} and to use {@link createDecipheriv} to create the `Decipher` object. - * @since v0.1.94 - * @deprecated Since v10.0.0 - Use {@link createDecipheriv} instead. - * @param options `stream.transform` options - */ - function createDecipher(algorithm: CipherCCMTypes, password: BinaryLike, options: CipherCCMOptions): DecipherCCM; - /** @deprecated since v10.0.0 use `createDecipheriv()` */ - function createDecipher(algorithm: CipherGCMTypes, password: BinaryLike, options?: CipherGCMOptions): DecipherGCM; - /** @deprecated since v10.0.0 use `createDecipheriv()` */ - function createDecipher(algorithm: string, password: BinaryLike, options?: stream.TransformOptions): Decipher; - /** - * Creates and returns a `Decipher` object that uses the given `algorithm`, `key` and initialization vector (`iv`). + * Creates and returns a `Decipheriv` object that uses the given `algorithm`, `key` and initialization vector (`iv`). * * The `options` argument controls stream behavior and is optional except when a * cipher in CCM or OCB mode (e.g. `'aes-128-ccm'`) is used. In that case, the `authTagLength` option is required and specifies the length of the @@ -1055,14 +1001,20 @@ declare module "crypto" { iv: BinaryLike, options?: CipherGCMOptions, ): DecipherGCM; + function createDecipheriv( + algorithm: CipherChaCha20Poly1305Types, + key: CipherKey, + iv: BinaryLike, + options?: CipherChaCha20Poly1305Options, + ): DecipherChaCha20Poly1305; function createDecipheriv( algorithm: string, key: CipherKey, iv: BinaryLike | null, options?: stream.TransformOptions, - ): Decipher; + ): Decipheriv; /** - * Instances of the `Decipher` class are used to decrypt data. The class can be + * Instances of the `Decipheriv` class are used to decrypt data. The class can be * used in one of two ways: * * * As a `stream` that is both readable and writable, where plain encrypted @@ -1070,11 +1022,11 @@ declare module "crypto" { * * Using the `decipher.update()` and `decipher.final()` methods to * produce the unencrypted data. * - * The {@link createDecipher} or {@link createDecipheriv} methods are - * used to create `Decipher` instances. `Decipher` objects are not to be created + * The {@link createDecipheriv} method is + * used to create `Decipheriv` instances. `Decipheriv` objects are not to be created * directly using the `new` keyword. * - * Example: Using `Decipher` objects as streams: + * Example: Using `Decipheriv` objects as streams: * * ```js * import { Buffer } from 'node:buffer'; @@ -1113,7 +1065,7 @@ declare module "crypto" { * decipher.end(); * ``` * - * Example: Using `Decipher` and piped streams: + * Example: Using `Decipheriv` and piped streams: * * ```js * import { @@ -1169,7 +1121,7 @@ declare module "crypto" { * ``` * @since v0.1.94 */ - class Decipher extends stream.Transform { + class Decipheriv extends stream.Transform { private constructor(); /** * Updates the decipher with `data`. If the `inputEncoding` argument is given, @@ -1185,19 +1137,19 @@ declare module "crypto" { * @param inputEncoding The `encoding` of the `data` string. * @param outputEncoding The `encoding` of the return value. */ - update(data: NodeJS.ArrayBufferView): Buffer; - update(data: string, inputEncoding: Encoding): Buffer; + update(data: NodeJS.ArrayBufferView): NonSharedBuffer; + update(data: string, inputEncoding: Encoding): NonSharedBuffer; update(data: NodeJS.ArrayBufferView, inputEncoding: undefined, outputEncoding: Encoding): string; update(data: string, inputEncoding: Encoding | undefined, outputEncoding: Encoding): string; /** - * Once the `decipher.final()` method has been called, the `Decipher` object can + * Once the `decipher.final()` method has been called, the `Decipheriv` object can * no longer be used to decrypt data. Attempts to call `decipher.final()` more * than once will result in an error being thrown. * @since v0.1.94 * @param outputEncoding The `encoding` of the return value. * @return Any remaining deciphered contents. If `outputEncoding` is specified, a string is returned. If an `outputEncoding` is not provided, a {@link Buffer} is returned. */ - final(): Buffer; + final(): NonSharedBuffer; final(outputEncoding: BufferEncoding): string; /** * When data has been encrypted without standard block padding, calling `decipher.setAutoPadding(false)` will disable automatic padding to prevent `decipher.final()` from checking for and @@ -1213,7 +1165,7 @@ declare module "crypto" { */ setAutoPadding(auto_padding?: boolean): this; } - interface DecipherCCM extends Decipher { + interface DecipherCCM extends Decipheriv { setAuthTag(buffer: NodeJS.ArrayBufferView): this; setAAD( buffer: NodeJS.ArrayBufferView, @@ -1222,7 +1174,7 @@ declare module "crypto" { }, ): this; } - interface DecipherGCM extends Decipher { + interface DecipherGCM extends Decipheriv { setAuthTag(buffer: NodeJS.ArrayBufferView): this; setAAD( buffer: NodeJS.ArrayBufferView, @@ -1231,7 +1183,7 @@ declare module "crypto" { }, ): this; } - interface DecipherOCB extends Decipher { + interface DecipherOCB extends Decipheriv { setAuthTag(buffer: NodeJS.ArrayBufferView): this; setAAD( buffer: NodeJS.ArrayBufferView, @@ -1240,6 +1192,15 @@ declare module "crypto" { }, ): this; } + interface DecipherChaCha20Poly1305 extends Decipheriv { + setAuthTag(buffer: NodeJS.ArrayBufferView): this; + setAAD( + buffer: NodeJS.ArrayBufferView, + options: { + plaintextLength: number; + }, + ): this; + } interface PrivateKeyInput { key: string | Buffer; format?: KeyFormat | undefined; @@ -1350,6 +1311,7 @@ declare module "crypto" { * @since v0.1.92 * @param options `stream.Writable` options */ + // TODO: signing algorithm type function createSign(algorithm: string, options?: stream.WritableOptions): Sign; type DSAEncoding = "der" | "ieee-p1363"; interface SigningOptions { @@ -1359,6 +1321,7 @@ declare module "crypto" { padding?: number | undefined; saltLength?: number | undefined; dsaEncoding?: DSAEncoding | undefined; + context?: ArrayBuffer | NodeJS.ArrayBufferView | undefined; } interface SignPrivateKeyInput extends PrivateKeyInput, SigningOptions {} interface SignKeyObjectInput extends SigningOptions { @@ -1460,7 +1423,7 @@ declare module "crypto" { * called. Multiple calls to `sign.sign()` will result in an error being thrown. * @since v0.1.92 */ - sign(privateKey: KeyLike | SignKeyObjectInput | SignPrivateKeyInput | SignJsonWebKeyInput): Buffer; + sign(privateKey: KeyLike | SignKeyObjectInput | SignPrivateKeyInput | SignJsonWebKeyInput): NonSharedBuffer; sign( privateKey: KeyLike | SignKeyObjectInput | SignPrivateKeyInput | SignJsonWebKeyInput, outputFormat: BinaryToTextEncoding, @@ -1619,7 +1582,7 @@ declare module "crypto" { * @since v0.5.0 * @param encoding The `encoding` of the return value. */ - generateKeys(): Buffer; + generateKeys(): NonSharedBuffer; generateKeys(encoding: BinaryToTextEncoding): string; /** * Computes the shared secret using `otherPublicKey` as the other @@ -1634,8 +1597,16 @@ declare module "crypto" { * @param inputEncoding The `encoding` of an `otherPublicKey` string. * @param outputEncoding The `encoding` of the return value. */ - computeSecret(otherPublicKey: NodeJS.ArrayBufferView, inputEncoding?: null, outputEncoding?: null): Buffer; - computeSecret(otherPublicKey: string, inputEncoding: BinaryToTextEncoding, outputEncoding?: null): Buffer; + computeSecret( + otherPublicKey: NodeJS.ArrayBufferView, + inputEncoding?: null, + outputEncoding?: null, + ): NonSharedBuffer; + computeSecret( + otherPublicKey: string, + inputEncoding: BinaryToTextEncoding, + outputEncoding?: null, + ): NonSharedBuffer; computeSecret( otherPublicKey: NodeJS.ArrayBufferView, inputEncoding: null, @@ -1653,7 +1624,7 @@ declare module "crypto" { * @since v0.5.0 * @param encoding The `encoding` of the return value. */ - getPrime(): Buffer; + getPrime(): NonSharedBuffer; getPrime(encoding: BinaryToTextEncoding): string; /** * Returns the Diffie-Hellman generator in the specified `encoding`. @@ -1662,7 +1633,7 @@ declare module "crypto" { * @since v0.5.0 * @param encoding The `encoding` of the return value. */ - getGenerator(): Buffer; + getGenerator(): NonSharedBuffer; getGenerator(encoding: BinaryToTextEncoding): string; /** * Returns the Diffie-Hellman public key in the specified `encoding`. @@ -1671,7 +1642,7 @@ declare module "crypto" { * @since v0.5.0 * @param encoding The `encoding` of the return value. */ - getPublicKey(): Buffer; + getPublicKey(): NonSharedBuffer; getPublicKey(encoding: BinaryToTextEncoding): string; /** * Returns the Diffie-Hellman private key in the specified `encoding`. @@ -1680,7 +1651,7 @@ declare module "crypto" { * @since v0.5.0 * @param encoding The `encoding` of the return value. */ - getPrivateKey(): Buffer; + getPrivateKey(): NonSharedBuffer; getPrivateKey(encoding: BinaryToTextEncoding): string; /** * Sets the Diffie-Hellman public key. If the `encoding` argument is provided, `publicKey` is expected @@ -1824,7 +1795,7 @@ declare module "crypto" { iterations: number, keylen: number, digest: string, - callback: (err: Error | null, derivedKey: Buffer) => void, + callback: (err: Error | null, derivedKey: NonSharedBuffer) => void, ): void; /** * Provides a synchronous Password-Based Key Derivation Function 2 (PBKDF2) @@ -1861,7 +1832,7 @@ declare module "crypto" { iterations: number, keylen: number, digest: string, - ): Buffer; + ): NonSharedBuffer; /** * Generates cryptographically strong pseudorandom data. The `size` argument * is a number indicating the number of bytes to generate. @@ -1914,10 +1885,10 @@ declare module "crypto" { * @param size The number of bytes to generate. The `size` must not be larger than `2**31 - 1`. * @return if the `callback` function is not provided. */ - function randomBytes(size: number): Buffer; - function randomBytes(size: number, callback: (err: Error | null, buf: Buffer) => void): void; - function pseudoRandomBytes(size: number): Buffer; - function pseudoRandomBytes(size: number, callback: (err: Error | null, buf: Buffer) => void): void; + function randomBytes(size: number): NonSharedBuffer; + function randomBytes(size: number, callback: (err: Error | null, buf: NonSharedBuffer) => void): void; + function pseudoRandomBytes(size: number): NonSharedBuffer; + function pseudoRandomBytes(size: number, callback: (err: Error | null, buf: NonSharedBuffer) => void): void; /** * Return a random integer `n` such that `min <= n < max`. This * implementation avoids [modulo bias](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#Modulo_bias). @@ -2147,14 +2118,14 @@ declare module "crypto" { password: BinaryLike, salt: BinaryLike, keylen: number, - callback: (err: Error | null, derivedKey: Buffer) => void, + callback: (err: Error | null, derivedKey: NonSharedBuffer) => void, ): void; function scrypt( password: BinaryLike, salt: BinaryLike, keylen: number, options: ScryptOptions, - callback: (err: Error | null, derivedKey: Buffer) => void, + callback: (err: Error | null, derivedKey: NonSharedBuffer) => void, ): void; /** * Provides a synchronous [scrypt](https://en.wikipedia.org/wiki/Scrypt) implementation. Scrypt is a password-based @@ -2186,7 +2157,12 @@ declare module "crypto" { * ``` * @since v10.5.0 */ - function scryptSync(password: BinaryLike, salt: BinaryLike, keylen: number, options?: ScryptOptions): Buffer; + function scryptSync( + password: BinaryLike, + salt: BinaryLike, + keylen: number, + options?: ScryptOptions, + ): NonSharedBuffer; interface RsaPublicKey { key: KeyLike; padding?: number | undefined; @@ -2212,7 +2188,10 @@ declare module "crypto" { * be passed instead of a public key. * @since v0.11.14 */ - function publicEncrypt(key: RsaPublicKey | RsaPrivateKey | KeyLike, buffer: NodeJS.ArrayBufferView): Buffer; + function publicEncrypt( + key: RsaPublicKey | RsaPrivateKey | KeyLike, + buffer: NodeJS.ArrayBufferView | string, + ): NonSharedBuffer; /** * Decrypts `buffer` with `key`.`buffer` was previously encrypted using * the corresponding private key, for example using {@link privateEncrypt}. @@ -2224,7 +2203,10 @@ declare module "crypto" { * be passed instead of a public key. * @since v1.1.0 */ - function publicDecrypt(key: RsaPublicKey | RsaPrivateKey | KeyLike, buffer: NodeJS.ArrayBufferView): Buffer; + function publicDecrypt( + key: RsaPublicKey | RsaPrivateKey | KeyLike, + buffer: NodeJS.ArrayBufferView | string, + ): NonSharedBuffer; /** * Decrypts `buffer` with `privateKey`. `buffer` was previously encrypted using * the corresponding public key, for example using {@link publicEncrypt}. @@ -2233,7 +2215,10 @@ declare module "crypto" { * object, the `padding` property can be passed. Otherwise, this function uses `RSA_PKCS1_OAEP_PADDING`. * @since v0.11.14 */ - function privateDecrypt(privateKey: RsaPrivateKey | KeyLike, buffer: NodeJS.ArrayBufferView): Buffer; + function privateDecrypt( + privateKey: RsaPrivateKey | KeyLike, + buffer: NodeJS.ArrayBufferView | string, + ): NonSharedBuffer; /** * Encrypts `buffer` with `privateKey`. The returned data can be decrypted using * the corresponding public key, for example using {@link publicDecrypt}. @@ -2242,7 +2227,10 @@ declare module "crypto" { * object, the `padding` property can be passed. Otherwise, this function uses `RSA_PKCS1_PADDING`. * @since v1.1.0 */ - function privateEncrypt(privateKey: RsaPrivateKey | KeyLike, buffer: NodeJS.ArrayBufferView): Buffer; + function privateEncrypt( + privateKey: RsaPrivateKey | KeyLike, + buffer: NodeJS.ArrayBufferView | string, + ): NonSharedBuffer; /** * ```js * const { @@ -2371,7 +2359,7 @@ declare module "crypto" { inputEncoding?: BinaryToTextEncoding, outputEncoding?: "latin1" | "hex" | "base64" | "base64url", format?: "uncompressed" | "compressed" | "hybrid", - ): Buffer | string; + ): NonSharedBuffer | string; /** * Generates private and public EC Diffie-Hellman key values, and returns * the public key in the specified `format` and `encoding`. This key should be @@ -2384,7 +2372,7 @@ declare module "crypto" { * @param encoding The `encoding` of the return value. * @param [format='uncompressed'] */ - generateKeys(): Buffer; + generateKeys(): NonSharedBuffer; generateKeys(encoding: BinaryToTextEncoding, format?: ECDHKeyFormat): string; /** * Computes the shared secret using `otherPublicKey` as the other @@ -2403,8 +2391,8 @@ declare module "crypto" { * @param inputEncoding The `encoding` of the `otherPublicKey` string. * @param outputEncoding The `encoding` of the return value. */ - computeSecret(otherPublicKey: NodeJS.ArrayBufferView): Buffer; - computeSecret(otherPublicKey: string, inputEncoding: BinaryToTextEncoding): Buffer; + computeSecret(otherPublicKey: NodeJS.ArrayBufferView): NonSharedBuffer; + computeSecret(otherPublicKey: string, inputEncoding: BinaryToTextEncoding): NonSharedBuffer; computeSecret(otherPublicKey: NodeJS.ArrayBufferView, outputEncoding: BinaryToTextEncoding): string; computeSecret( otherPublicKey: string, @@ -2418,7 +2406,7 @@ declare module "crypto" { * @param encoding The `encoding` of the return value. * @return The EC Diffie-Hellman in the specified `encoding`. */ - getPrivateKey(): Buffer; + getPrivateKey(): NonSharedBuffer; getPrivateKey(encoding: BinaryToTextEncoding): string; /** * The `format` argument specifies point encoding and can be `'compressed'` or `'uncompressed'`. If `format` is not specified the point will be returned in`'uncompressed'` format. @@ -2430,7 +2418,7 @@ declare module "crypto" { * @param [format='uncompressed'] * @return The EC Diffie-Hellman public key in the specified `encoding` and `format`. */ - getPublicKey(encoding?: null, format?: ECDHKeyFormat): Buffer; + getPublicKey(encoding?: null, format?: ECDHKeyFormat): NonSharedBuffer; getPublicKey(encoding: BinaryToTextEncoding, format?: ECDHKeyFormat): string; /** * Sets the EC Diffie-Hellman private key. @@ -2480,7 +2468,34 @@ declare module "crypto" { * @since v6.6.0 */ function timingSafeEqual(a: NodeJS.ArrayBufferView, b: NodeJS.ArrayBufferView): boolean; - type KeyType = "rsa" | "rsa-pss" | "dsa" | "ec" | "ed25519" | "ed448" | "x25519" | "x448"; + type KeyType = + | "dh" + | "dsa" + | "ec" + | "ed25519" + | "ed448" + | "ml-dsa-44" + | "ml-dsa-65" + | "ml-dsa-87" + | "ml-kem-1024" + | "ml-kem-512" + | "ml-kem-768" + | "rsa-pss" + | "rsa" + | "slh-dsa-sha2-128f" + | "slh-dsa-sha2-128s" + | "slh-dsa-sha2-192f" + | "slh-dsa-sha2-192s" + | "slh-dsa-sha2-256f" + | "slh-dsa-sha2-256s" + | "slh-dsa-shake-128f" + | "slh-dsa-shake-128s" + | "slh-dsa-shake-192f" + | "slh-dsa-shake-192s" + | "slh-dsa-shake-256f" + | "slh-dsa-shake-256s" + | "x25519" + | "x448"; type KeyFormat = "pem" | "der" | "jwk"; interface BasePrivateKeyEncodingOptions { format: T; @@ -2495,6 +2510,9 @@ declare module "crypto" { interface ED448KeyPairKeyObjectOptions {} interface X25519KeyPairKeyObjectOptions {} interface X448KeyPairKeyObjectOptions {} + interface MLDSAKeyPairKeyObjectOptions {} + interface MLKEMKeyPairKeyObjectOptions {} + interface SLHDSAKeyPairKeyObjectOptions {} interface ECKeyPairKeyObjectOptions { /** * Name of the curve to use @@ -2529,15 +2547,15 @@ declare module "crypto" { /** * Name of the message digest */ - hashAlgorithm?: string; + hashAlgorithm?: string | undefined; /** * Name of the message digest used by MGF1 */ - mgf1HashAlgorithm?: string; + mgf1HashAlgorithm?: string | undefined; /** * Minimal salt length in bytes */ - saltLength?: string; + saltLength?: string | undefined; } interface DSAKeyPairKeyObjectOptions { /** @@ -2580,15 +2598,15 @@ declare module "crypto" { /** * Name of the message digest */ - hashAlgorithm?: string; + hashAlgorithm?: string | undefined; /** * Name of the message digest used by MGF1 */ - mgf1HashAlgorithm?: string; + mgf1HashAlgorithm?: string | undefined; /** * Minimal salt length in bytes */ - saltLength?: string; + saltLength?: string | undefined; publicKeyEncoding: { type: "spki"; format: PubF; @@ -2659,13 +2677,40 @@ declare module "crypto" { type: "pkcs8"; }; } + interface MLDSAKeyPairOptions { + publicKeyEncoding: { + type: "spki"; + format: PubF; + }; + privateKeyEncoding: BasePrivateKeyEncodingOptions & { + type: "pkcs8"; + }; + } + interface MLKEMKeyPairOptions { + publicKeyEncoding: { + type: "spki"; + format: PubF; + }; + privateKeyEncoding: BasePrivateKeyEncodingOptions & { + type: "pkcs8"; + }; + } + interface SLHDSAKeyPairOptions { + publicKeyEncoding: { + type: "spki"; + format: PubF; + }; + privateKeyEncoding: BasePrivateKeyEncodingOptions & { + type: "pkcs8"; + }; + } interface KeyPairSyncResult { publicKey: T1; privateKey: T2; } /** * Generates a new asymmetric key pair of the given `type`. RSA, RSA-PSS, DSA, EC, - * Ed25519, Ed448, X25519, X448, and DH are currently supported. + * Ed25519, Ed448, X25519, X448, DH, and ML-DSA are currently supported. * * If a `publicKeyEncoding` or `privateKeyEncoding` was specified, this function * behaves as if `keyObject.export()` had been called on its result. Otherwise, @@ -2702,7 +2747,8 @@ declare module "crypto" { * When PEM encoding was selected, the respective key will be a string, otherwise * it will be a buffer containing the data encoded as DER. * @since v10.12.0 - * @param type Must be `'rsa'`, `'rsa-pss'`, `'dsa'`, `'ec'`, `'ed25519'`, `'ed448'`, `'x25519'`, `'x448'`, or `'dh'`. + * @param type The asymmetric key type to generate. See the + * supported [asymmetric key types](https://nodejs.org/docs/latest-v24.x/api/crypto.html#asymmetric-key-types). */ function generateKeyPairSync( type: "rsa", @@ -2711,15 +2757,15 @@ declare module "crypto" { function generateKeyPairSync( type: "rsa", options: RSAKeyPairOptions<"pem", "der">, - ): KeyPairSyncResult; + ): KeyPairSyncResult; function generateKeyPairSync( type: "rsa", options: RSAKeyPairOptions<"der", "pem">, - ): KeyPairSyncResult; + ): KeyPairSyncResult; function generateKeyPairSync( type: "rsa", options: RSAKeyPairOptions<"der", "der">, - ): KeyPairSyncResult; + ): KeyPairSyncResult; function generateKeyPairSync(type: "rsa", options: RSAKeyPairKeyObjectOptions): KeyPairKeyObjectResult; function generateKeyPairSync( type: "rsa-pss", @@ -2728,15 +2774,15 @@ declare module "crypto" { function generateKeyPairSync( type: "rsa-pss", options: RSAPSSKeyPairOptions<"pem", "der">, - ): KeyPairSyncResult; + ): KeyPairSyncResult; function generateKeyPairSync( type: "rsa-pss", options: RSAPSSKeyPairOptions<"der", "pem">, - ): KeyPairSyncResult; + ): KeyPairSyncResult; function generateKeyPairSync( type: "rsa-pss", options: RSAPSSKeyPairOptions<"der", "der">, - ): KeyPairSyncResult; + ): KeyPairSyncResult; function generateKeyPairSync(type: "rsa-pss", options: RSAPSSKeyPairKeyObjectOptions): KeyPairKeyObjectResult; function generateKeyPairSync( type: "dsa", @@ -2745,15 +2791,15 @@ declare module "crypto" { function generateKeyPairSync( type: "dsa", options: DSAKeyPairOptions<"pem", "der">, - ): KeyPairSyncResult; + ): KeyPairSyncResult; function generateKeyPairSync( type: "dsa", options: DSAKeyPairOptions<"der", "pem">, - ): KeyPairSyncResult; + ): KeyPairSyncResult; function generateKeyPairSync( type: "dsa", options: DSAKeyPairOptions<"der", "der">, - ): KeyPairSyncResult; + ): KeyPairSyncResult; function generateKeyPairSync(type: "dsa", options: DSAKeyPairKeyObjectOptions): KeyPairKeyObjectResult; function generateKeyPairSync( type: "ec", @@ -2762,15 +2808,15 @@ declare module "crypto" { function generateKeyPairSync( type: "ec", options: ECKeyPairOptions<"pem", "der">, - ): KeyPairSyncResult; + ): KeyPairSyncResult; function generateKeyPairSync( type: "ec", options: ECKeyPairOptions<"der", "pem">, - ): KeyPairSyncResult; + ): KeyPairSyncResult; function generateKeyPairSync( type: "ec", options: ECKeyPairOptions<"der", "der">, - ): KeyPairSyncResult; + ): KeyPairSyncResult; function generateKeyPairSync(type: "ec", options: ECKeyPairKeyObjectOptions): KeyPairKeyObjectResult; function generateKeyPairSync( type: "ed25519", @@ -2779,15 +2825,15 @@ declare module "crypto" { function generateKeyPairSync( type: "ed25519", options: ED25519KeyPairOptions<"pem", "der">, - ): KeyPairSyncResult; + ): KeyPairSyncResult; function generateKeyPairSync( type: "ed25519", options: ED25519KeyPairOptions<"der", "pem">, - ): KeyPairSyncResult; + ): KeyPairSyncResult; function generateKeyPairSync( type: "ed25519", options: ED25519KeyPairOptions<"der", "der">, - ): KeyPairSyncResult; + ): KeyPairSyncResult; function generateKeyPairSync(type: "ed25519", options?: ED25519KeyPairKeyObjectOptions): KeyPairKeyObjectResult; function generateKeyPairSync( type: "ed448", @@ -2796,15 +2842,15 @@ declare module "crypto" { function generateKeyPairSync( type: "ed448", options: ED448KeyPairOptions<"pem", "der">, - ): KeyPairSyncResult; + ): KeyPairSyncResult; function generateKeyPairSync( type: "ed448", options: ED448KeyPairOptions<"der", "pem">, - ): KeyPairSyncResult; + ): KeyPairSyncResult; function generateKeyPairSync( type: "ed448", options: ED448KeyPairOptions<"der", "der">, - ): KeyPairSyncResult; + ): KeyPairSyncResult; function generateKeyPairSync(type: "ed448", options?: ED448KeyPairKeyObjectOptions): KeyPairKeyObjectResult; function generateKeyPairSync( type: "x25519", @@ -2813,15 +2859,15 @@ declare module "crypto" { function generateKeyPairSync( type: "x25519", options: X25519KeyPairOptions<"pem", "der">, - ): KeyPairSyncResult; + ): KeyPairSyncResult; function generateKeyPairSync( type: "x25519", options: X25519KeyPairOptions<"der", "pem">, - ): KeyPairSyncResult; + ): KeyPairSyncResult; function generateKeyPairSync( type: "x25519", options: X25519KeyPairOptions<"der", "der">, - ): KeyPairSyncResult; + ): KeyPairSyncResult; function generateKeyPairSync(type: "x25519", options?: X25519KeyPairKeyObjectOptions): KeyPairKeyObjectResult; function generateKeyPairSync( type: "x448", @@ -2830,16 +2876,136 @@ declare module "crypto" { function generateKeyPairSync( type: "x448", options: X448KeyPairOptions<"pem", "der">, - ): KeyPairSyncResult; + ): KeyPairSyncResult; function generateKeyPairSync( type: "x448", options: X448KeyPairOptions<"der", "pem">, - ): KeyPairSyncResult; + ): KeyPairSyncResult; function generateKeyPairSync( type: "x448", options: X448KeyPairOptions<"der", "der">, - ): KeyPairSyncResult; + ): KeyPairSyncResult; function generateKeyPairSync(type: "x448", options?: X448KeyPairKeyObjectOptions): KeyPairKeyObjectResult; + function generateKeyPairSync( + type: "ml-dsa-44" | "ml-dsa-65" | "ml-dsa-87", + options: MLDSAKeyPairOptions<"pem", "pem">, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: "ml-dsa-44" | "ml-dsa-65" | "ml-dsa-87", + options: MLDSAKeyPairOptions<"pem", "der">, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: "ml-dsa-44" | "ml-dsa-65" | "ml-dsa-87", + options: MLDSAKeyPairOptions<"der", "pem">, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: "ml-dsa-44" | "ml-dsa-65" | "ml-dsa-87", + options: MLDSAKeyPairOptions<"der", "der">, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: "ml-dsa-44" | "ml-dsa-65" | "ml-dsa-87", + options?: MLDSAKeyPairKeyObjectOptions, + ): KeyPairKeyObjectResult; + function generateKeyPairSync( + type: "ml-kem-1024" | "ml-kem-512" | "ml-kem-768", + options: MLKEMKeyPairOptions<"pem", "pem">, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: "ml-kem-1024" | "ml-kem-512" | "ml-kem-768", + options: MLKEMKeyPairOptions<"pem", "der">, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: "ml-kem-1024" | "ml-kem-512" | "ml-kem-768", + options: MLKEMKeyPairOptions<"der", "pem">, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: "ml-kem-1024" | "ml-kem-512" | "ml-kem-768", + options: MLKEMKeyPairOptions<"der", "der">, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: "ml-kem-1024" | "ml-kem-512" | "ml-kem-768", + options?: MLKEMKeyPairKeyObjectOptions, + ): KeyPairKeyObjectResult; + function generateKeyPairSync( + type: + | "slh-dsa-sha2-128f" + | "slh-dsa-sha2-128s" + | "slh-dsa-sha2-192f" + | "slh-dsa-sha2-192s" + | "slh-dsa-sha2-256f" + | "slh-dsa-sha2-256s" + | "slh-dsa-shake-128f" + | "slh-dsa-shake-128s" + | "slh-dsa-shake-192f" + | "slh-dsa-shake-192s" + | "slh-dsa-shake-256f" + | "slh-dsa-shake-256s", + options: SLHDSAKeyPairOptions<"pem", "pem">, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: + | "slh-dsa-sha2-128f" + | "slh-dsa-sha2-128s" + | "slh-dsa-sha2-192f" + | "slh-dsa-sha2-192s" + | "slh-dsa-sha2-256f" + | "slh-dsa-sha2-256s" + | "slh-dsa-shake-128f" + | "slh-dsa-shake-128s" + | "slh-dsa-shake-192f" + | "slh-dsa-shake-192s" + | "slh-dsa-shake-256f" + | "slh-dsa-shake-256s", + options: SLHDSAKeyPairOptions<"pem", "der">, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: + | "slh-dsa-sha2-128f" + | "slh-dsa-sha2-128s" + | "slh-dsa-sha2-192f" + | "slh-dsa-sha2-192s" + | "slh-dsa-sha2-256f" + | "slh-dsa-sha2-256s" + | "slh-dsa-shake-128f" + | "slh-dsa-shake-128s" + | "slh-dsa-shake-192f" + | "slh-dsa-shake-192s" + | "slh-dsa-shake-256f" + | "slh-dsa-shake-256s", + options: SLHDSAKeyPairOptions<"der", "pem">, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: + | "slh-dsa-sha2-128f" + | "slh-dsa-sha2-128s" + | "slh-dsa-sha2-192f" + | "slh-dsa-sha2-192s" + | "slh-dsa-sha2-256f" + | "slh-dsa-sha2-256s" + | "slh-dsa-shake-128f" + | "slh-dsa-shake-128s" + | "slh-dsa-shake-192f" + | "slh-dsa-shake-192s" + | "slh-dsa-shake-256f" + | "slh-dsa-shake-256s", + options: SLHDSAKeyPairOptions<"der", "der">, + ): KeyPairSyncResult; + function generateKeyPairSync( + type: + | "slh-dsa-sha2-128f" + | "slh-dsa-sha2-128s" + | "slh-dsa-sha2-192f" + | "slh-dsa-sha2-192s" + | "slh-dsa-sha2-256f" + | "slh-dsa-sha2-256s" + | "slh-dsa-shake-128f" + | "slh-dsa-shake-128s" + | "slh-dsa-shake-192f" + | "slh-dsa-shake-192s" + | "slh-dsa-shake-256f" + | "slh-dsa-shake-256s", + options?: SLHDSAKeyPairKeyObjectOptions, + ): KeyPairKeyObjectResult; /** * Generates a new asymmetric key pair of the given `type`. RSA, RSA-PSS, DSA, EC, * Ed25519, Ed448, X25519, X448, and DH are currently supported. @@ -2877,7 +3043,8 @@ declare module "crypto" { * If this method is invoked as its `util.promisify()` ed version, it returns * a `Promise` for an `Object` with `publicKey` and `privateKey` properties. * @since v10.12.0 - * @param type Must be `'rsa'`, `'rsa-pss'`, `'dsa'`, `'ec'`, `'ed25519'`, `'ed448'`, `'x25519'`, `'x448'`, or `'dh'`. + * @param type The asymmetric key type to generate. See the + * supported [asymmetric key types](https://nodejs.org/docs/latest-v24.x/api/crypto.html#asymmetric-key-types). */ function generateKeyPair( type: "rsa", @@ -2887,17 +3054,17 @@ declare module "crypto" { function generateKeyPair( type: "rsa", options: RSAKeyPairOptions<"pem", "der">, - callback: (err: Error | null, publicKey: string, privateKey: Buffer) => void, + callback: (err: Error | null, publicKey: string, privateKey: NonSharedBuffer) => void, ): void; function generateKeyPair( type: "rsa", options: RSAKeyPairOptions<"der", "pem">, - callback: (err: Error | null, publicKey: Buffer, privateKey: string) => void, + callback: (err: Error | null, publicKey: NonSharedBuffer, privateKey: string) => void, ): void; function generateKeyPair( type: "rsa", options: RSAKeyPairOptions<"der", "der">, - callback: (err: Error | null, publicKey: Buffer, privateKey: Buffer) => void, + callback: (err: Error | null, publicKey: NonSharedBuffer, privateKey: NonSharedBuffer) => void, ): void; function generateKeyPair( type: "rsa", @@ -2912,17 +3079,17 @@ declare module "crypto" { function generateKeyPair( type: "rsa-pss", options: RSAPSSKeyPairOptions<"pem", "der">, - callback: (err: Error | null, publicKey: string, privateKey: Buffer) => void, + callback: (err: Error | null, publicKey: string, privateKey: NonSharedBuffer) => void, ): void; function generateKeyPair( type: "rsa-pss", options: RSAPSSKeyPairOptions<"der", "pem">, - callback: (err: Error | null, publicKey: Buffer, privateKey: string) => void, + callback: (err: Error | null, publicKey: NonSharedBuffer, privateKey: string) => void, ): void; function generateKeyPair( type: "rsa-pss", options: RSAPSSKeyPairOptions<"der", "der">, - callback: (err: Error | null, publicKey: Buffer, privateKey: Buffer) => void, + callback: (err: Error | null, publicKey: NonSharedBuffer, privateKey: NonSharedBuffer) => void, ): void; function generateKeyPair( type: "rsa-pss", @@ -2937,17 +3104,17 @@ declare module "crypto" { function generateKeyPair( type: "dsa", options: DSAKeyPairOptions<"pem", "der">, - callback: (err: Error | null, publicKey: string, privateKey: Buffer) => void, + callback: (err: Error | null, publicKey: string, privateKey: NonSharedBuffer) => void, ): void; function generateKeyPair( type: "dsa", options: DSAKeyPairOptions<"der", "pem">, - callback: (err: Error | null, publicKey: Buffer, privateKey: string) => void, + callback: (err: Error | null, publicKey: NonSharedBuffer, privateKey: string) => void, ): void; function generateKeyPair( type: "dsa", options: DSAKeyPairOptions<"der", "der">, - callback: (err: Error | null, publicKey: Buffer, privateKey: Buffer) => void, + callback: (err: Error | null, publicKey: NonSharedBuffer, privateKey: NonSharedBuffer) => void, ): void; function generateKeyPair( type: "dsa", @@ -2962,17 +3129,17 @@ declare module "crypto" { function generateKeyPair( type: "ec", options: ECKeyPairOptions<"pem", "der">, - callback: (err: Error | null, publicKey: string, privateKey: Buffer) => void, + callback: (err: Error | null, publicKey: string, privateKey: NonSharedBuffer) => void, ): void; function generateKeyPair( type: "ec", options: ECKeyPairOptions<"der", "pem">, - callback: (err: Error | null, publicKey: Buffer, privateKey: string) => void, + callback: (err: Error | null, publicKey: NonSharedBuffer, privateKey: string) => void, ): void; function generateKeyPair( type: "ec", options: ECKeyPairOptions<"der", "der">, - callback: (err: Error | null, publicKey: Buffer, privateKey: Buffer) => void, + callback: (err: Error | null, publicKey: NonSharedBuffer, privateKey: NonSharedBuffer) => void, ): void; function generateKeyPair( type: "ec", @@ -2987,17 +3154,17 @@ declare module "crypto" { function generateKeyPair( type: "ed25519", options: ED25519KeyPairOptions<"pem", "der">, - callback: (err: Error | null, publicKey: string, privateKey: Buffer) => void, + callback: (err: Error | null, publicKey: string, privateKey: NonSharedBuffer) => void, ): void; function generateKeyPair( type: "ed25519", options: ED25519KeyPairOptions<"der", "pem">, - callback: (err: Error | null, publicKey: Buffer, privateKey: string) => void, + callback: (err: Error | null, publicKey: NonSharedBuffer, privateKey: string) => void, ): void; function generateKeyPair( type: "ed25519", options: ED25519KeyPairOptions<"der", "der">, - callback: (err: Error | null, publicKey: Buffer, privateKey: Buffer) => void, + callback: (err: Error | null, publicKey: NonSharedBuffer, privateKey: NonSharedBuffer) => void, ): void; function generateKeyPair( type: "ed25519", @@ -3012,17 +3179,17 @@ declare module "crypto" { function generateKeyPair( type: "ed448", options: ED448KeyPairOptions<"pem", "der">, - callback: (err: Error | null, publicKey: string, privateKey: Buffer) => void, + callback: (err: Error | null, publicKey: string, privateKey: NonSharedBuffer) => void, ): void; function generateKeyPair( type: "ed448", options: ED448KeyPairOptions<"der", "pem">, - callback: (err: Error | null, publicKey: Buffer, privateKey: string) => void, + callback: (err: Error | null, publicKey: NonSharedBuffer, privateKey: string) => void, ): void; function generateKeyPair( type: "ed448", options: ED448KeyPairOptions<"der", "der">, - callback: (err: Error | null, publicKey: Buffer, privateKey: Buffer) => void, + callback: (err: Error | null, publicKey: NonSharedBuffer, privateKey: NonSharedBuffer) => void, ): void; function generateKeyPair( type: "ed448", @@ -3037,17 +3204,17 @@ declare module "crypto" { function generateKeyPair( type: "x25519", options: X25519KeyPairOptions<"pem", "der">, - callback: (err: Error | null, publicKey: string, privateKey: Buffer) => void, + callback: (err: Error | null, publicKey: string, privateKey: NonSharedBuffer) => void, ): void; function generateKeyPair( type: "x25519", options: X25519KeyPairOptions<"der", "pem">, - callback: (err: Error | null, publicKey: Buffer, privateKey: string) => void, + callback: (err: Error | null, publicKey: NonSharedBuffer, privateKey: string) => void, ): void; function generateKeyPair( type: "x25519", options: X25519KeyPairOptions<"der", "der">, - callback: (err: Error | null, publicKey: Buffer, privateKey: Buffer) => void, + callback: (err: Error | null, publicKey: NonSharedBuffer, privateKey: NonSharedBuffer) => void, ): void; function generateKeyPair( type: "x25519", @@ -3062,23 +3229,158 @@ declare module "crypto" { function generateKeyPair( type: "x448", options: X448KeyPairOptions<"pem", "der">, - callback: (err: Error | null, publicKey: string, privateKey: Buffer) => void, + callback: (err: Error | null, publicKey: string, privateKey: NonSharedBuffer) => void, ): void; function generateKeyPair( type: "x448", options: X448KeyPairOptions<"der", "pem">, - callback: (err: Error | null, publicKey: Buffer, privateKey: string) => void, + callback: (err: Error | null, publicKey: NonSharedBuffer, privateKey: string) => void, ): void; function generateKeyPair( type: "x448", options: X448KeyPairOptions<"der", "der">, - callback: (err: Error | null, publicKey: Buffer, privateKey: Buffer) => void, + callback: (err: Error | null, publicKey: NonSharedBuffer, privateKey: NonSharedBuffer) => void, ): void; function generateKeyPair( type: "x448", options: X448KeyPairKeyObjectOptions | undefined, callback: (err: Error | null, publicKey: KeyObject, privateKey: KeyObject) => void, ): void; + function generateKeyPair( + type: "ml-dsa-44" | "ml-dsa-65" | "ml-dsa-87", + options: MLDSAKeyPairOptions<"pem", "pem">, + callback: (err: Error | null, publicKey: string, privateKey: string) => void, + ): void; + function generateKeyPair( + type: "ml-dsa-44" | "ml-dsa-65" | "ml-dsa-87", + options: MLDSAKeyPairOptions<"pem", "der">, + callback: (err: Error | null, publicKey: string, privateKey: NonSharedBuffer) => void, + ): void; + function generateKeyPair( + type: "ml-dsa-44" | "ml-dsa-65" | "ml-dsa-87", + options: MLDSAKeyPairOptions<"der", "pem">, + callback: (err: Error | null, publicKey: NonSharedBuffer, privateKey: string) => void, + ): void; + function generateKeyPair( + type: "ml-dsa-44" | "ml-dsa-65" | "ml-dsa-87", + options: MLDSAKeyPairOptions<"der", "der">, + callback: (err: Error | null, publicKey: NonSharedBuffer, privateKey: NonSharedBuffer) => void, + ): void; + function generateKeyPair( + type: "ml-dsa-44" | "ml-dsa-65" | "ml-dsa-87", + options: MLDSAKeyPairKeyObjectOptions | undefined, + callback: (err: Error | null, publicKey: KeyObject, privateKey: KeyObject) => void, + ): void; + function generateKeyPair( + type: "ml-kem-1024" | "ml-kem-512" | "ml-kem-768", + options: MLKEMKeyPairOptions<"pem", "pem">, + callback: (err: Error | null, publicKey: string, privateKey: string) => void, + ): void; + function generateKeyPair( + type: "ml-kem-1024" | "ml-kem-512" | "ml-kem-768", + options: MLKEMKeyPairOptions<"pem", "der">, + callback: (err: Error | null, publicKey: string, privateKey: NonSharedBuffer) => void, + ): void; + function generateKeyPair( + type: "ml-kem-1024" | "ml-kem-512" | "ml-kem-768", + options: MLKEMKeyPairOptions<"der", "pem">, + callback: (err: Error | null, publicKey: NonSharedBuffer, privateKey: string) => void, + ): void; + function generateKeyPair( + type: "ml-kem-1024" | "ml-kem-512" | "ml-kem-768", + options: MLKEMKeyPairOptions<"der", "der">, + callback: (err: Error | null, publicKey: NonSharedBuffer, privateKey: NonSharedBuffer) => void, + ): void; + function generateKeyPair( + type: "ml-kem-1024" | "ml-kem-512" | "ml-kem-768", + options: MLKEMKeyPairKeyObjectOptions | undefined, + callback: (err: Error | null, publicKey: KeyObject, privateKey: KeyObject) => void, + ): void; + function generateKeyPair( + type: + | "slh-dsa-sha2-128f" + | "slh-dsa-sha2-128s" + | "slh-dsa-sha2-192f" + | "slh-dsa-sha2-192s" + | "slh-dsa-sha2-256f" + | "slh-dsa-sha2-256s" + | "slh-dsa-shake-128f" + | "slh-dsa-shake-128s" + | "slh-dsa-shake-192f" + | "slh-dsa-shake-192s" + | "slh-dsa-shake-256f" + | "slh-dsa-shake-256s", + options: SLHDSAKeyPairOptions<"pem", "pem">, + callback: (err: Error | null, publicKey: string, privateKey: string) => void, + ): void; + function generateKeyPair( + type: + | "slh-dsa-sha2-128f" + | "slh-dsa-sha2-128s" + | "slh-dsa-sha2-192f" + | "slh-dsa-sha2-192s" + | "slh-dsa-sha2-256f" + | "slh-dsa-sha2-256s" + | "slh-dsa-shake-128f" + | "slh-dsa-shake-128s" + | "slh-dsa-shake-192f" + | "slh-dsa-shake-192s" + | "slh-dsa-shake-256f" + | "slh-dsa-shake-256s", + options: SLHDSAKeyPairOptions<"pem", "der">, + callback: (err: Error | null, publicKey: string, privateKey: Buffer) => void, + ): void; + function generateKeyPair( + type: + | "slh-dsa-sha2-128f" + | "slh-dsa-sha2-128s" + | "slh-dsa-sha2-192f" + | "slh-dsa-sha2-192s" + | "slh-dsa-sha2-256f" + | "slh-dsa-sha2-256s" + | "slh-dsa-shake-128f" + | "slh-dsa-shake-128s" + | "slh-dsa-shake-192f" + | "slh-dsa-shake-192s" + | "slh-dsa-shake-256f" + | "slh-dsa-shake-256s", + options: SLHDSAKeyPairOptions<"der", "pem">, + callback: (err: Error | null, publicKey: Buffer, privateKey: string) => void, + ): void; + function generateKeyPair( + type: + | "slh-dsa-sha2-128f" + | "slh-dsa-sha2-128s" + | "slh-dsa-sha2-192f" + | "slh-dsa-sha2-192s" + | "slh-dsa-sha2-256f" + | "slh-dsa-sha2-256s" + | "slh-dsa-shake-128f" + | "slh-dsa-shake-128s" + | "slh-dsa-shake-192f" + | "slh-dsa-shake-192s" + | "slh-dsa-shake-256f" + | "slh-dsa-shake-256s", + options: SLHDSAKeyPairOptions<"der", "der">, + callback: (err: Error | null, publicKey: Buffer, privateKey: Buffer) => void, + ): void; + function generateKeyPair( + type: + | "slh-dsa-sha2-128f" + | "slh-dsa-sha2-128s" + | "slh-dsa-sha2-192f" + | "slh-dsa-sha2-192s" + | "slh-dsa-sha2-256f" + | "slh-dsa-sha2-256s" + | "slh-dsa-shake-128f" + | "slh-dsa-shake-128s" + | "slh-dsa-shake-192f" + | "slh-dsa-shake-192s" + | "slh-dsa-shake-256f" + | "slh-dsa-shake-256s", + options: SLHDSAKeyPairKeyObjectOptions | undefined, + callback: (err: Error | null, publicKey: KeyObject, privateKey: KeyObject) => void, + ): void; namespace generateKeyPair { function __promisify__( type: "rsa", @@ -3092,21 +3394,21 @@ declare module "crypto" { options: RSAKeyPairOptions<"pem", "der">, ): Promise<{ publicKey: string; - privateKey: Buffer; + privateKey: NonSharedBuffer; }>; function __promisify__( type: "rsa", options: RSAKeyPairOptions<"der", "pem">, ): Promise<{ - publicKey: Buffer; + publicKey: NonSharedBuffer; privateKey: string; }>; function __promisify__( type: "rsa", options: RSAKeyPairOptions<"der", "der">, ): Promise<{ - publicKey: Buffer; - privateKey: Buffer; + publicKey: NonSharedBuffer; + privateKey: NonSharedBuffer; }>; function __promisify__(type: "rsa", options: RSAKeyPairKeyObjectOptions): Promise; function __promisify__( @@ -3121,21 +3423,21 @@ declare module "crypto" { options: RSAPSSKeyPairOptions<"pem", "der">, ): Promise<{ publicKey: string; - privateKey: Buffer; + privateKey: NonSharedBuffer; }>; function __promisify__( type: "rsa-pss", options: RSAPSSKeyPairOptions<"der", "pem">, ): Promise<{ - publicKey: Buffer; + publicKey: NonSharedBuffer; privateKey: string; }>; function __promisify__( type: "rsa-pss", options: RSAPSSKeyPairOptions<"der", "der">, ): Promise<{ - publicKey: Buffer; - privateKey: Buffer; + publicKey: NonSharedBuffer; + privateKey: NonSharedBuffer; }>; function __promisify__( type: "rsa-pss", @@ -3153,21 +3455,21 @@ declare module "crypto" { options: DSAKeyPairOptions<"pem", "der">, ): Promise<{ publicKey: string; - privateKey: Buffer; + privateKey: NonSharedBuffer; }>; function __promisify__( type: "dsa", options: DSAKeyPairOptions<"der", "pem">, ): Promise<{ - publicKey: Buffer; + publicKey: NonSharedBuffer; privateKey: string; }>; function __promisify__( type: "dsa", options: DSAKeyPairOptions<"der", "der">, ): Promise<{ - publicKey: Buffer; - privateKey: Buffer; + publicKey: NonSharedBuffer; + privateKey: NonSharedBuffer; }>; function __promisify__(type: "dsa", options: DSAKeyPairKeyObjectOptions): Promise; function __promisify__( @@ -3182,21 +3484,21 @@ declare module "crypto" { options: ECKeyPairOptions<"pem", "der">, ): Promise<{ publicKey: string; - privateKey: Buffer; + privateKey: NonSharedBuffer; }>; function __promisify__( type: "ec", options: ECKeyPairOptions<"der", "pem">, ): Promise<{ - publicKey: Buffer; + publicKey: NonSharedBuffer; privateKey: string; }>; function __promisify__( type: "ec", options: ECKeyPairOptions<"der", "der">, ): Promise<{ - publicKey: Buffer; - privateKey: Buffer; + publicKey: NonSharedBuffer; + privateKey: NonSharedBuffer; }>; function __promisify__(type: "ec", options: ECKeyPairKeyObjectOptions): Promise; function __promisify__( @@ -3211,21 +3513,21 @@ declare module "crypto" { options: ED25519KeyPairOptions<"pem", "der">, ): Promise<{ publicKey: string; - privateKey: Buffer; + privateKey: NonSharedBuffer; }>; function __promisify__( type: "ed25519", options: ED25519KeyPairOptions<"der", "pem">, ): Promise<{ - publicKey: Buffer; + publicKey: NonSharedBuffer; privateKey: string; }>; function __promisify__( type: "ed25519", options: ED25519KeyPairOptions<"der", "der">, ): Promise<{ - publicKey: Buffer; - privateKey: Buffer; + publicKey: NonSharedBuffer; + privateKey: NonSharedBuffer; }>; function __promisify__( type: "ed25519", @@ -3243,21 +3545,21 @@ declare module "crypto" { options: ED448KeyPairOptions<"pem", "der">, ): Promise<{ publicKey: string; - privateKey: Buffer; + privateKey: NonSharedBuffer; }>; function __promisify__( type: "ed448", options: ED448KeyPairOptions<"der", "pem">, ): Promise<{ - publicKey: Buffer; + publicKey: NonSharedBuffer; privateKey: string; }>; function __promisify__( type: "ed448", options: ED448KeyPairOptions<"der", "der">, ): Promise<{ - publicKey: Buffer; - privateKey: Buffer; + publicKey: NonSharedBuffer; + privateKey: NonSharedBuffer; }>; function __promisify__(type: "ed448", options?: ED448KeyPairKeyObjectOptions): Promise; function __promisify__( @@ -3272,21 +3574,21 @@ declare module "crypto" { options: X25519KeyPairOptions<"pem", "der">, ): Promise<{ publicKey: string; - privateKey: Buffer; + privateKey: NonSharedBuffer; }>; function __promisify__( type: "x25519", options: X25519KeyPairOptions<"der", "pem">, ): Promise<{ - publicKey: Buffer; + publicKey: NonSharedBuffer; privateKey: string; }>; function __promisify__( type: "x25519", options: X25519KeyPairOptions<"der", "der">, ): Promise<{ - publicKey: Buffer; - privateKey: Buffer; + publicKey: NonSharedBuffer; + privateKey: NonSharedBuffer; }>; function __promisify__( type: "x25519", @@ -3304,28 +3606,187 @@ declare module "crypto" { options: X448KeyPairOptions<"pem", "der">, ): Promise<{ publicKey: string; - privateKey: Buffer; + privateKey: NonSharedBuffer; }>; function __promisify__( type: "x448", options: X448KeyPairOptions<"der", "pem">, ): Promise<{ - publicKey: Buffer; + publicKey: NonSharedBuffer; privateKey: string; }>; function __promisify__( type: "x448", options: X448KeyPairOptions<"der", "der">, + ): Promise<{ + publicKey: NonSharedBuffer; + privateKey: NonSharedBuffer; + }>; + function __promisify__(type: "x448", options?: X448KeyPairKeyObjectOptions): Promise; + function __promisify__( + type: "ml-dsa-44" | "ml-dsa-65" | "ml-dsa-87", + options: MLDSAKeyPairOptions<"pem", "pem">, + ): Promise<{ + publicKey: string; + privateKey: string; + }>; + function __promisify__( + type: "ml-dsa-44" | "ml-dsa-65" | "ml-dsa-87", + options: MLDSAKeyPairOptions<"pem", "der">, + ): Promise<{ + publicKey: string; + privateKey: NonSharedBuffer; + }>; + function __promisify__( + type: "ml-dsa-44" | "ml-dsa-65" | "ml-dsa-87", + options: MLDSAKeyPairOptions<"der", "pem">, + ): Promise<{ + publicKey: NonSharedBuffer; + privateKey: string; + }>; + function __promisify__( + type: "ml-dsa-44" | "ml-dsa-65" | "ml-dsa-87", + options: MLDSAKeyPairOptions<"der", "der">, + ): Promise<{ + publicKey: NonSharedBuffer; + privateKey: NonSharedBuffer; + }>; + function __promisify__( + type: "ml-dsa-44" | "ml-dsa-65" | "ml-dsa-87", + options?: MLDSAKeyPairKeyObjectOptions, + ): Promise; + function __promisify__( + type: "ml-kem-1024" | "ml-kem-512" | "ml-kem-768", + options: MLKEMKeyPairOptions<"pem", "pem">, + ): Promise<{ + publicKey: string; + privateKey: string; + }>; + function __promisify__( + type: "ml-kem-1024" | "ml-kem-512" | "ml-kem-768", + options: MLKEMKeyPairOptions<"pem", "der">, + ): Promise<{ + publicKey: string; + privateKey: NonSharedBuffer; + }>; + function __promisify__( + type: "ml-kem-1024" | "ml-kem-512" | "ml-kem-768", + options: MLKEMKeyPairOptions<"der", "pem">, + ): Promise<{ + publicKey: NonSharedBuffer; + privateKey: string; + }>; + function __promisify__( + type: "ml-kem-1024" | "ml-kem-512" | "ml-kem-768", + options: MLKEMKeyPairOptions<"der", "der">, + ): Promise<{ + publicKey: NonSharedBuffer; + privateKey: NonSharedBuffer; + }>; + function __promisify__( + type: "ml-kem-1024" | "ml-kem-512" | "ml-kem-768", + options?: MLKEMKeyPairKeyObjectOptions, + ): Promise; + function __promisify__( + type: + | "slh-dsa-sha2-128f" + | "slh-dsa-sha2-128s" + | "slh-dsa-sha2-192f" + | "slh-dsa-sha2-192s" + | "slh-dsa-sha2-256f" + | "slh-dsa-sha2-256s" + | "slh-dsa-shake-128f" + | "slh-dsa-shake-128s" + | "slh-dsa-shake-192f" + | "slh-dsa-shake-192s" + | "slh-dsa-shake-256f" + | "slh-dsa-shake-256s", + options: SLHDSAKeyPairOptions<"pem", "pem">, + ): Promise<{ + publicKey: string; + privateKey: string; + }>; + function __promisify__( + type: + | "slh-dsa-sha2-128f" + | "slh-dsa-sha2-128s" + | "slh-dsa-sha2-192f" + | "slh-dsa-sha2-192s" + | "slh-dsa-sha2-256f" + | "slh-dsa-sha2-256s" + | "slh-dsa-shake-128f" + | "slh-dsa-shake-128s" + | "slh-dsa-shake-192f" + | "slh-dsa-shake-192s" + | "slh-dsa-shake-256f" + | "slh-dsa-shake-256s", + options: SLHDSAKeyPairOptions<"pem", "der">, + ): Promise<{ + publicKey: string; + privateKey: Buffer; + }>; + function __promisify__( + type: + | "slh-dsa-sha2-128f" + | "slh-dsa-sha2-128s" + | "slh-dsa-sha2-192f" + | "slh-dsa-sha2-192s" + | "slh-dsa-sha2-256f" + | "slh-dsa-sha2-256s" + | "slh-dsa-shake-128f" + | "slh-dsa-shake-128s" + | "slh-dsa-shake-192f" + | "slh-dsa-shake-192s" + | "slh-dsa-shake-256f" + | "slh-dsa-shake-256s", + options: SLHDSAKeyPairOptions<"der", "pem">, + ): Promise<{ + publicKey: Buffer; + privateKey: string; + }>; + function __promisify__( + type: + | "slh-dsa-sha2-128f" + | "slh-dsa-sha2-128s" + | "slh-dsa-sha2-192f" + | "slh-dsa-sha2-192s" + | "slh-dsa-sha2-256f" + | "slh-dsa-sha2-256s" + | "slh-dsa-shake-128f" + | "slh-dsa-shake-128s" + | "slh-dsa-shake-192f" + | "slh-dsa-shake-192s" + | "slh-dsa-shake-256f" + | "slh-dsa-shake-256s", + options: SLHDSAKeyPairOptions<"der", "der">, ): Promise<{ publicKey: Buffer; privateKey: Buffer; }>; - function __promisify__(type: "x448", options?: X448KeyPairKeyObjectOptions): Promise; + function __promisify__( + type: + | "slh-dsa-sha2-128f" + | "slh-dsa-sha2-128s" + | "slh-dsa-sha2-192f" + | "slh-dsa-sha2-192s" + | "slh-dsa-sha2-256f" + | "slh-dsa-sha2-256s" + | "slh-dsa-shake-128f" + | "slh-dsa-shake-128s" + | "slh-dsa-shake-192f" + | "slh-dsa-shake-192s" + | "slh-dsa-shake-256f" + | "slh-dsa-shake-256s", + options?: SLHDSAKeyPairKeyObjectOptions, + ): Promise; } /** * Calculates and returns the signature for `data` using the given private key and * algorithm. If `algorithm` is `null` or `undefined`, then the algorithm is - * dependent upon the key type (especially Ed25519 and Ed448). + * dependent upon the key type. + * + * `algorithm` is required to be `null` or `undefined` for Ed25519, Ed448, and + * ML-DSA. * * If `key` is not a `KeyObject`, this function behaves as if `key` had been * passed to {@link createPrivateKey}. If it is an object, the following @@ -3338,16 +3799,20 @@ declare module "crypto" { algorithm: string | null | undefined, data: NodeJS.ArrayBufferView, key: KeyLike | SignKeyObjectInput | SignPrivateKeyInput | SignJsonWebKeyInput, - ): Buffer; + ): NonSharedBuffer; function sign( algorithm: string | null | undefined, data: NodeJS.ArrayBufferView, key: KeyLike | SignKeyObjectInput | SignPrivateKeyInput | SignJsonWebKeyInput, - callback: (error: Error | null, data: Buffer) => void, + callback: (error: Error | null, data: NonSharedBuffer) => void, ): void; /** - * Verifies the given signature for `data` using the given key and algorithm. If `algorithm` is `null` or `undefined`, then the algorithm is dependent upon the - * key type (especially Ed25519 and Ed448). + * Verifies the given signature for `data` using the given key and algorithm. If + * `algorithm` is `null` or `undefined`, then the algorithm is dependent upon the + * key type. + * + * `algorithm` is required to be `null` or `undefined` for Ed25519, Ed448, and + * ML-DSA. * * If `key` is not a `KeyObject`, this function behaves as if `key` had been * passed to {@link createPublicKey}. If it is an object, the following @@ -3375,22 +3840,108 @@ declare module "crypto" { callback: (error: Error | null, result: boolean) => void, ): void; /** - * Computes the Diffie-Hellman secret based on a `privateKey` and a `publicKey`. - * Both keys must have the same `asymmetricKeyType`, which must be one of `'dh'` (for Diffie-Hellman), `'ec'` (for ECDH), `'x448'`, or `'x25519'` (for ECDH-ES). + * Key decapsulation using a KEM algorithm with a private key. + * + * Supported key types and their KEM algorithms are: + * + * * `'rsa'` RSA Secret Value Encapsulation + * * `'ec'` DHKEM(P-256, HKDF-SHA256), DHKEM(P-384, HKDF-SHA256), DHKEM(P-521, HKDF-SHA256) + * * `'x25519'` DHKEM(X25519, HKDF-SHA256) + * * `'x448'` DHKEM(X448, HKDF-SHA512) + * * `'ml-kem-512'` ML-KEM + * * `'ml-kem-768'` ML-KEM + * * `'ml-kem-1024'` ML-KEM + * + * If `key` is not a {@link KeyObject}, this function behaves as if `key` had been + * passed to `crypto.createPrivateKey()`. + * + * If the `callback` function is provided this function uses libuv's threadpool. + * @since v24.7.0 + */ + function decapsulate( + key: KeyLike | PrivateKeyInput | JsonWebKeyInput, + ciphertext: ArrayBuffer | NodeJS.ArrayBufferView, + ): NonSharedBuffer; + function decapsulate( + key: KeyLike | PrivateKeyInput | JsonWebKeyInput, + ciphertext: ArrayBuffer | NodeJS.ArrayBufferView, + callback: (err: Error, sharedKey: NonSharedBuffer) => void, + ): void; + /** + * Computes the Diffie-Hellman shared secret based on a `privateKey` and a `publicKey`. + * Both keys must have the same `asymmetricKeyType` and must support either the DH or + * ECDH operation. + * + * If the `callback` function is provided this function uses libuv's threadpool. * @since v13.9.0, v12.17.0 */ - function diffieHellman(options: { privateKey: KeyObject; publicKey: KeyObject }): Buffer; + function diffieHellman(options: { privateKey: KeyObject; publicKey: KeyObject }): NonSharedBuffer; + function diffieHellman( + options: { privateKey: KeyObject; publicKey: KeyObject }, + callback: (err: Error | null, secret: NonSharedBuffer) => void, + ): void; /** - * A utility for creating one-shot hash digests of data. It can be faster than the object-based `crypto.createHash()` when hashing a smaller amount of data - * (<= 5MB) that's readily available. If the data can be big or if it is streamed, it's still recommended to use `crypto.createHash()` instead. The `algorithm` - * is dependent on the available algorithms supported by the version of OpenSSL on the platform. Examples are `'sha256'`, `'sha512'`, etc. On recent releases - * of OpenSSL, `openssl list -digest-algorithms` will display the available digest algorithms. + * Key encapsulation using a KEM algorithm with a public key. + * + * Supported key types and their KEM algorithms are: + * + * * `'rsa'` RSA Secret Value Encapsulation + * * `'ec'` DHKEM(P-256, HKDF-SHA256), DHKEM(P-384, HKDF-SHA256), DHKEM(P-521, HKDF-SHA256) + * * `'x25519'` DHKEM(X25519, HKDF-SHA256) + * * `'x448'` DHKEM(X448, HKDF-SHA512) + * * `'ml-kem-512'` ML-KEM + * * `'ml-kem-768'` ML-KEM + * * `'ml-kem-1024'` ML-KEM + * + * If `key` is not a {@link KeyObject}, this function behaves as if `key` had been + * passed to `crypto.createPublicKey()`. + * + * If the `callback` function is provided this function uses libuv's threadpool. + * @since v24.7.0 + */ + function encapsulate( + key: KeyLike | PublicKeyInput | JsonWebKeyInput, + ): { sharedKey: NonSharedBuffer; ciphertext: NonSharedBuffer }; + function encapsulate( + key: KeyLike | PublicKeyInput | JsonWebKeyInput, + callback: (err: Error, result: { sharedKey: NonSharedBuffer; ciphertext: NonSharedBuffer }) => void, + ): void; + interface OneShotDigestOptions { + /** + * Encoding used to encode the returned digest. + * @default 'hex' + */ + outputEncoding?: BinaryToTextEncoding | "buffer" | undefined; + /** + * For XOF hash functions such as 'shake256', the outputLength option + * can be used to specify the desired output length in bytes. + */ + outputLength?: number | undefined; + } + interface OneShotDigestOptionsWithStringEncoding extends OneShotDigestOptions { + outputEncoding?: BinaryToTextEncoding | undefined; + } + interface OneShotDigestOptionsWithBufferEncoding extends OneShotDigestOptions { + outputEncoding: "buffer"; + } + /** + * A utility for creating one-shot hash digests of data. It can be faster than + * the object-based `crypto.createHash()` when hashing a smaller amount of data + * (<= 5MB) that's readily available. If the data can be big or if it is streamed, + * it's still recommended to use `crypto.createHash()` instead. + * + * The `algorithm` is dependent on the available algorithms supported by the + * version of OpenSSL on the platform. Examples are `'sha256'`, `'sha512'`, etc. + * On recent releases of OpenSSL, `openssl list -digest-algorithms` will + * display the available digest algorithms. + * + * If `options` is a string, then it specifies the `outputEncoding`. * * Example: * * ```js - * const crypto = require('node:crypto'); - * const { Buffer } = require('node:buffer'); + * import crypto from 'node:crypto'; + * import { Buffer } from 'node:buffer'; * * // Hashing a string and return the result as a hex-encoded string. * const string = 'Node.js'; @@ -3404,17 +3955,26 @@ declare module "crypto" { * console.log(crypto.hash('sha1', Buffer.from(base64, 'base64'), 'buffer')); * ``` * @since v21.7.0, v20.12.0 - * @param data When `data` is a string, it will be encoded as UTF-8 before being hashed. If a different input encoding is desired for a string input, user - * could encode the string into a `TypedArray` using either `TextEncoder` or `Buffer.from()` and passing the encoded `TypedArray` into this API instead. - * @param [outputEncoding='hex'] [Encoding](https://nodejs.org/docs/latest-v20.x/api/buffer.html#buffers-and-character-encodings) used to encode the returned digest. + * @param data When `data` is a string, it will be encoded as UTF-8 before being hashed. If a different + * input encoding is desired for a string input, user could encode the string + * into a `TypedArray` using either `TextEncoder` or `Buffer.from()` and passing + * the encoded `TypedArray` into this API instead. */ - function hash(algorithm: string, data: BinaryLike, outputEncoding?: BinaryToTextEncoding): string; - function hash(algorithm: string, data: BinaryLike, outputEncoding: "buffer"): Buffer; function hash( algorithm: string, data: BinaryLike, - outputEncoding?: BinaryToTextEncoding | "buffer", - ): string | Buffer; + options?: OneShotDigestOptionsWithStringEncoding | BinaryToTextEncoding, + ): string; + function hash( + algorithm: string, + data: BinaryLike, + options: OneShotDigestOptionsWithBufferEncoding | "buffer", + ): NonSharedBuffer; + function hash( + algorithm: string, + data: BinaryLike, + options: OneShotDigestOptions | BinaryToTextEncoding | "buffer", + ): string | NonSharedBuffer; type CipherMode = "cbc" | "ccm" | "cfb" | "ctr" | "ecb" | "gcm" | "ocb" | "ofb" | "stream" | "wrap" | "xts"; interface CipherInfoOptions { /** @@ -3578,23 +4138,23 @@ declare module "crypto" { /** * @default 'always' */ - subject?: "always" | "default" | "never"; + subject?: "always" | "default" | "never" | undefined; /** * @default true */ - wildcards?: boolean; + wildcards?: boolean | undefined; /** * @default true */ - partialWildcards?: boolean; + partialWildcards?: boolean | undefined; /** * @default false */ - multiLabelWildcards?: boolean; + multiLabelWildcards?: boolean | undefined; /** * @default false */ - singleLabelSubdomains?: boolean; + singleLabelSubdomains?: boolean | undefined; } /** * Encapsulates an X509 certificate and provides read-only access to @@ -3696,7 +4256,7 @@ declare module "crypto" { * available. * @since v15.9.0 */ - readonly issuerCertificate?: X509Certificate | undefined; + readonly issuerCertificate: X509Certificate | undefined; /** * The public key `KeyObject` for this certificate. * @since v15.6.0 @@ -3706,7 +4266,7 @@ declare module "crypto" { * A `Buffer` containing the DER encoding of this certificate. * @since v15.6.0 */ - readonly raw: Buffer; + readonly raw: NonSharedBuffer; /** * The serial number of this certificate. * @@ -3716,16 +4276,36 @@ declare module "crypto" { * @since v15.6.0 */ readonly serialNumber: string; + /** + * The algorithm used to sign the certificate or `undefined` if the signature algorithm is unknown by OpenSSL. + * @since v24.9.0 + */ + readonly signatureAlgorithm: string | undefined; + /** + * The OID of the algorithm used to sign the certificate. + * @since v24.9.0 + */ + readonly signatureAlgorithmOid: string; /** * The date/time from which this certificate is considered valid. * @since v15.6.0 */ readonly validFrom: string; + /** + * The date/time from which this certificate is valid, encapsulated in a `Date` object. + * @since v22.10.0 + */ + readonly validFromDate: Date; /** * The date/time until which this certificate is considered valid. * @since v15.6.0 */ readonly validTo: string; + /** + * The date/time until which this certificate is valid, encapsulated in a `Date` object. + * @since v22.10.0 + */ + readonly validToDate: Date; constructor(buffer: BinaryLike); /** * Checks whether the certificate matches the given email address. @@ -3778,7 +4358,23 @@ declare module "crypto" { */ checkIP(ip: string): string | undefined; /** - * Checks whether this certificate was issued by the given `otherCert`. + * Checks whether this certificate was potentially issued by the given `otherCert` + * by comparing the certificate metadata. + * + * This is useful for pruning a list of possible issuer certificates which have been + * selected using a more rudimentary filtering routine, i.e. just based on subject + * and issuer names. + * + * Finally, to verify that this certificate's signature was produced by a private key + * corresponding to `otherCert`'s public key use `x509.verify(publicKey)` + * with `otherCert`'s public key represented as a `KeyObject` + * like so + * + * ```js + * if (!x509.verify(otherCert.publicKey)) { + * throw new Error('otherCert did not issue x509'); + * } + * ``` * @since v15.6.0 */ checkIssued(otherCert: X509Certificate): boolean; @@ -3962,6 +4558,130 @@ declare module "crypto" { * @return Returns `typedArray`. */ function getRandomValues(typedArray: T): T; + type Argon2Algorithm = "argon2d" | "argon2i" | "argon2id"; + interface Argon2Parameters { + /** + * REQUIRED, this is the password for password hashing applications of Argon2. + */ + message: string | ArrayBuffer | NodeJS.ArrayBufferView; + /** + * REQUIRED, must be at least 8 bytes long. This is the salt for password hashing applications of Argon2. + */ + nonce: string | ArrayBuffer | NodeJS.ArrayBufferView; + /** + * REQUIRED, degree of parallelism determines how many computational chains (lanes) + * can be run. Must be greater than 1 and less than `2**24-1`. + */ + parallelism: number; + /** + * REQUIRED, the length of the key to generate. Must be greater than 4 and + * less than `2**32-1`. + */ + tagLength: number; + /** + * REQUIRED, memory cost in 1KiB blocks. Must be greater than + * `8 * parallelism` and less than `2**32-1`. The actual number of blocks is rounded + * down to the nearest multiple of `4 * parallelism`. + */ + memory: number; + /** + * REQUIRED, number of passes (iterations). Must be greater than 1 and less + * than `2**32-1`. + */ + passes: number; + /** + * OPTIONAL, Random additional input, + * similar to the salt, that should **NOT** be stored with the derived key. This is known as pepper in + * password hashing applications. If used, must have a length not greater than `2**32-1` bytes. + */ + secret?: string | ArrayBuffer | NodeJS.ArrayBufferView | undefined; + /** + * OPTIONAL, Additional data to + * be added to the hash, functionally equivalent to salt or secret, but meant for + * non-random data. If used, must have a length not greater than `2**32-1` bytes. + */ + associatedData?: string | ArrayBuffer | NodeJS.ArrayBufferView | undefined; + } + /** + * Provides an asynchronous [Argon2](https://www.rfc-editor.org/rfc/rfc9106.html) implementation. Argon2 is a password-based + * key derivation function that is designed to be expensive computationally and + * memory-wise in order to make brute-force attacks unrewarding. + * + * The `nonce` should be as unique as possible. It is recommended that a nonce is + * random and at least 16 bytes long. See [NIST SP 800-132](https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-132.pdf) for details. + * + * When passing strings for `message`, `nonce`, `secret` or `associatedData`, please + * consider [caveats when using strings as inputs to cryptographic APIs](https://nodejs.org/docs/latest-v24.x/api/crypto.html#using-strings-as-inputs-to-cryptographic-apis). + * + * The `callback` function is called with two arguments: `err` and `derivedKey`. + * `err` is an exception object when key derivation fails, otherwise `err` is + * `null`. `derivedKey` is passed to the callback as a `Buffer`. + * + * An exception is thrown when any of the input arguments specify invalid values + * or types. + * + * ```js + * const { argon2, randomBytes } = await import('node:crypto'); + * + * const parameters = { + * message: 'password', + * nonce: randomBytes(16), + * parallelism: 4, + * tagLength: 64, + * memory: 65536, + * passes: 3, + * }; + * + * argon2('argon2id', parameters, (err, derivedKey) => { + * if (err) throw err; + * console.log(derivedKey.toString('hex')); // 'af91dad...9520f15' + * }); + * ``` + * @since v24.7.0 + * @param algorithm Variant of Argon2, one of `"argon2d"`, `"argon2i"` or `"argon2id"`. + * @experimental + */ + function argon2( + algorithm: Argon2Algorithm, + parameters: Argon2Parameters, + callback: (err: Error | null, derivedKey: NonSharedBuffer) => void, + ): void; + /** + * Provides a synchronous [Argon2][] implementation. Argon2 is a password-based + * key derivation function that is designed to be expensive computationally and + * memory-wise in order to make brute-force attacks unrewarding. + * + * The `nonce` should be as unique as possible. It is recommended that a nonce is + * random and at least 16 bytes long. See [NIST SP 800-132](https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-132.pdf) for details. + * + * When passing strings for `message`, `nonce`, `secret` or `associatedData`, please + * consider [caveats when using strings as inputs to cryptographic APIs](https://nodejs.org/docs/latest-v24.x/api/crypto.html#using-strings-as-inputs-to-cryptographic-apis). + * + * An exception is thrown when key derivation fails, otherwise the derived key is + * returned as a `Buffer`. + * + * An exception is thrown when any of the input arguments specify invalid values + * or types. + * + * ```js + * const { argon2Sync, randomBytes } = await import('node:crypto'); + * + * const parameters = { + * message: 'password', + * nonce: randomBytes(16), + * parallelism: 4, + * tagLength: 64, + * memory: 65536, + * passes: 3, + * }; + * + * const derivedKey = argon2Sync('argon2id', parameters); + * console.log(derivedKey.toString('hex')); // 'af91dad...9520f15' + * ``` + * @since v24.7.0 + * @experimental + */ + function argon2Sync(algorithm: Argon2Algorithm, parameters: Argon2Parameters): NonSharedBuffer; /** * A convenient alias for `crypto.webcrypto.subtle`. * @since v17.4.0 @@ -3976,21 +4696,30 @@ declare module "crypto" { const webcrypto: webcrypto.Crypto; namespace webcrypto { type BufferSource = ArrayBufferView | ArrayBuffer; - type KeyFormat = "jwk" | "pkcs8" | "raw" | "spki"; + type KeyFormat = "jwk" | "pkcs8" | "raw" | "raw-public" | "raw-secret" | "raw-seed" | "spki"; type KeyType = "private" | "public" | "secret"; type KeyUsage = - | "decrypt" - | "deriveBits" - | "deriveKey" | "encrypt" + | "decrypt" | "sign" - | "unwrapKey" | "verify" - | "wrapKey"; + | "deriveKey" + | "deriveBits" + | "encapsulateBits" + | "decapsulateBits" + | "encapsulateKey" + | "decapsulateKey" + | "wrapKey" + | "unwrapKey"; type AlgorithmIdentifier = Algorithm | string; type HashAlgorithmIdentifier = AlgorithmIdentifier; type NamedCurve = string; type BigInteger = Uint8Array; + interface AeadParams extends Algorithm { + additionalData?: BufferSource; + iv: BufferSource; + tagLength: number; + } interface AesCbcParams extends Algorithm { iv: BufferSource; } @@ -4001,6 +4730,8 @@ declare module "crypto" { interface AesDerivedKeyParams extends Algorithm { length: number; } + // TODO: remove in next major + /** @deprecated Replaced by `AeadParams`. */ interface AesGcmParams extends Algorithm { additionalData?: BufferSource; iv: BufferSource; @@ -4015,6 +4746,23 @@ declare module "crypto" { interface Algorithm { name: string; } + interface Argon2Params extends Algorithm { + associatedData?: BufferSource; + memory: number; + nonce: BufferSource; + parallelism: number; + passes: number; + secretValue?: BufferSource; + version?: number; + } + interface CShakeParams extends Algorithm { + customization?: BufferSource; + functionName?: BufferSource; + length: number; + } + interface ContextParams extends Algorithm { + context?: BufferSource; + } interface EcKeyAlgorithm extends KeyAlgorithm { namedCurve: NamedCurve; } @@ -4030,9 +4778,6 @@ declare module "crypto" { interface EcdsaParams extends Algorithm { hash: HashAlgorithmIdentifier; } - interface Ed448Params extends Algorithm { - context?: BufferSource; - } interface HkdfParams extends Algorithm { hash: HashAlgorithmIdentifier; info: BufferSource; @@ -4073,6 +4818,19 @@ declare module "crypto" { interface KeyAlgorithm { name: string; } + interface KmacImportParams extends Algorithm { + length?: number; + } + interface KmacKeyAlgorithm extends KeyAlgorithm { + length: number; + } + interface KmacKeyGenParams extends Algorithm { + length?: number; + } + interface KmacParams extends Algorithm { + customization?: BufferSource; + length: number; + } interface Pbkdf2Params extends Algorithm { hash: HashAlgorithmIdentifier; iterations: number; @@ -4107,7 +4865,7 @@ declare module "crypto" { saltLength: number; } /** - * Calling `require('node:crypto').webcrypto` returns an instance of the `Crypto` class. + * Importing the `webcrypto` object (`import { webcrypto } from 'node:crypto'`) gives an instance of the `Crypto` class. * `Crypto` is a singleton that provides access to the remainder of the crypto API. * @since v15.0.0 */ @@ -4126,22 +4884,15 @@ declare module "crypto" { * An error will be thrown if the given `typedArray` is larger than 65,536 bytes. * @since v15.0.0 */ - getRandomValues>(typedArray: T): T; + getRandomValues>( + typedArray: T, + ): T; /** * Generates a random {@link https://www.rfc-editor.org/rfc/rfc4122.txt RFC 4122} version 4 UUID. * The UUID is generated using a cryptographic pseudorandom number generator. * @since v16.7.0 */ randomUUID(): UUID; - CryptoKey: CryptoKeyConstructor; - } - // This constructor throws ILLEGAL_CONSTRUCTOR so it should not be newable. - interface CryptoKeyConstructor { - /** Illegal constructor */ - (_: { readonly _: unique symbol }): never; // Allows instanceof to work but not be callable by the user. - readonly length: 0; - readonly name: "CryptoKey"; - readonly prototype: CryptoKey; } /** * @since v15.0.0 @@ -4196,31 +4947,81 @@ declare module "crypto" { */ publicKey: CryptoKey; } + interface EncapsulatedBits { + sharedKey: ArrayBuffer; + ciphertext: ArrayBuffer; + } + interface EncapsulatedKey { + sharedKey: CryptoKey; + ciphertext: ArrayBuffer; + } /** * @since v15.0.0 */ interface SubtleCrypto { + /** + * A message recipient uses their asymmetric private key to decrypt an + * "encapsulated key" (ciphertext), thereby recovering a temporary symmetric + * key (represented as `ArrayBuffer`) which is then used to decrypt a message. + * + * The algorithms currently supported include: + * + * * `'ML-KEM-512'` + * * `'ML-KEM-768'` + * * `'ML-KEM-1024'` + * @since v24.7.0 + * @returns Fulfills with `ArrayBuffer` upon success. + */ + decapsulateBits( + decapsulationAlgorithm: AlgorithmIdentifier, + decapsulationKey: CryptoKey, + ciphertext: BufferSource, + ): Promise; + /** + * A message recipient uses their asymmetric private key to decrypt an + * "encapsulated key" (ciphertext), thereby recovering a temporary symmetric + * key (represented as `CryptoKey`) which is then used to decrypt a message. + * + * The algorithms currently supported include: + * + * * `'ML-KEM-512'` + * * `'ML-KEM-768'` + * * `'ML-KEM-1024'` + * @since v24.7.0 + * @param usages See [Key usages](https://nodejs.org/docs/latest-v24.x/api/webcrypto.html#cryptokeyusages). + * @returns Fulfills with `CryptoKey` upon success. + */ + decapsulateKey( + decapsulationAlgorithm: AlgorithmIdentifier, + decapsulationKey: CryptoKey, + ciphertext: BufferSource, + sharedKeyAlgorithm: AlgorithmIdentifier | HmacImportParams | AesDerivedKeyParams | KmacImportParams, + extractable: boolean, + usages: KeyUsage[], + ): Promise; /** * Using the method and parameters specified in `algorithm` and the keying material provided by `key`, - * `subtle.decrypt()` attempts to decipher the provided `data`. If successful, + * this method attempts to decipher the provided `data`. If successful, * the returned promise will be resolved with an `` containing the plaintext result. * * The algorithms currently supported include: * - * - `'RSA-OAEP'` - * - `'AES-CTR'` - * - `'AES-CBC'` - * - `'AES-GCM'` + * * `'AES-CBC'` + * * `'AES-CTR'` + * * `'AES-GCM'` + * * `'AES-OCB'` + * * `'ChaCha20-Poly1305'` + * * `'RSA-OAEP'` * @since v15.0.0 */ decrypt( - algorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AesGcmParams, + algorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AeadParams, key: CryptoKey, data: BufferSource, ): Promise; /** * Using the method and parameters specified in `algorithm` and the keying material provided by `baseKey`, - * `subtle.deriveBits()` attempts to generate `length` bits. + * this method attempts to generate `length` bits. * The Node.js implementation requires that when `length` is a number it must be multiple of `8`. * When `length` is `null` the maximum number of bits for a given algorithm is generated. This is allowed * for the `'ECDH'`, `'X25519'`, and `'X448'` algorithms. @@ -4228,45 +5029,50 @@ declare module "crypto" { * * The algorithms currently supported include: * - * - `'ECDH'` - * - `'X25519'` - * - `'X448'` - * - `'HKDF'` - * - `'PBKDF2'` + * * `'Argon2d'` + * * `'Argon2i'` + * * `'Argon2id'` + * * `'ECDH'` + * * `'HKDF'` + * * `'PBKDF2'` + * * `'X25519'` + * * `'X448'` * @since v15.0.0 */ - deriveBits(algorithm: EcdhKeyDeriveParams, baseKey: CryptoKey, length: number | null): Promise; deriveBits( - algorithm: AlgorithmIdentifier | HkdfParams | Pbkdf2Params, + algorithm: EcdhKeyDeriveParams, + baseKey: CryptoKey, + length?: number | null, + ): Promise; + deriveBits( + algorithm: EcdhKeyDeriveParams | HkdfParams | Pbkdf2Params | Argon2Params, baseKey: CryptoKey, length: number, ): Promise; /** * Using the method and parameters specified in `algorithm`, and the keying material provided by `baseKey`, - * `subtle.deriveKey()` attempts to generate a new ` based on the method and parameters in `derivedKeyAlgorithm`. + * this method attempts to generate a new ` based on the method and parameters in `derivedKeyAlgorithm`. * * Calling `subtle.deriveKey()` is equivalent to calling `subtle.deriveBits()` to generate raw keying material, * then passing the result into the `subtle.importKey()` method using the `deriveKeyAlgorithm`, `extractable`, and `keyUsages` parameters as input. * * The algorithms currently supported include: * - * - `'ECDH'` - * - `'X25519'` - * - `'X448'` - * - `'HKDF'` - * - `'PBKDF2'` + * * `'Argon2d'` + * * `'Argon2i'` + * * `'Argon2id'` + * * `'ECDH'` + * * `'HKDF'` + * * `'PBKDF2'` + * * `'X25519'` + * * `'X448'` * @param keyUsages See {@link https://nodejs.org/docs/latest/api/webcrypto.html#cryptokeyusages Key usages}. * @since v15.0.0 */ deriveKey( - algorithm: AlgorithmIdentifier | EcdhKeyDeriveParams | HkdfParams | Pbkdf2Params, + algorithm: EcdhKeyDeriveParams | HkdfParams | Pbkdf2Params | Argon2Params, baseKey: CryptoKey, - derivedKeyAlgorithm: - | AlgorithmIdentifier - | AesDerivedKeyParams - | HmacImportParams - | HkdfParams - | Pbkdf2Params, + derivedKeyAlgorithm: AlgorithmIdentifier | HmacImportParams | AesDerivedKeyParams | KmacImportParams, extractable: boolean, keyUsages: readonly KeyUsage[], ): Promise; @@ -4276,30 +5082,73 @@ declare module "crypto" { * * If `algorithm` is provided as a ``, it must be one of: * - * - `'SHA-1'` - * - `'SHA-256'` - * - `'SHA-384'` - * - `'SHA-512'` + * * `'cSHAKE128'` + * * `'cSHAKE256'` + * * `'SHA-1'` + * * `'SHA-256'` + * * `'SHA-384'` + * * `'SHA-512'` + * * `'SHA3-256'` + * * `'SHA3-384'` + * * `'SHA3-512'` * * If `algorithm` is provided as an ``, it must have a `name` property whose value is one of the above. * @since v15.0.0 */ - digest(algorithm: AlgorithmIdentifier, data: BufferSource): Promise; + digest(algorithm: AlgorithmIdentifier | CShakeParams, data: BufferSource): Promise; + /** + * Uses a message recipient's asymmetric public key to encrypt a temporary symmetric key. + * This encrypted key is the "encapsulated key" represented as `EncapsulatedBits`. + * + * The algorithms currently supported include: + * + * * `'ML-KEM-512'` + * * `'ML-KEM-768'` + * * `'ML-KEM-1024'` + * @since v24.7.0 + * @returns Fulfills with `EncapsulatedBits` upon success. + */ + encapsulateBits( + encapsulationAlgorithm: AlgorithmIdentifier, + encapsulationKey: CryptoKey, + ): Promise; + /** + * Uses a message recipient's asymmetric public key to encrypt a temporary symmetric key. + * This encrypted key is the "encapsulated key" represented as `EncapsulatedKey`. + * + * The algorithms currently supported include: + * + * * `'ML-KEM-512'` + * * `'ML-KEM-768'` + * * `'ML-KEM-1024'` + * @since v24.7.0 + * @param usages See [Key usages](https://nodejs.org/docs/latest-v24.x/api/webcrypto.html#cryptokeyusages). + * @returns Fulfills with `EncapsulatedKey` upon success. + */ + encapsulateKey( + encapsulationAlgorithm: AlgorithmIdentifier, + encapsulationKey: CryptoKey, + sharedKeyAlgorithm: AlgorithmIdentifier | HmacImportParams | AesDerivedKeyParams | KmacImportParams, + extractable: boolean, + usages: KeyUsage[], + ): Promise; /** * Using the method and parameters specified by `algorithm` and the keying material provided by `key`, - * `subtle.encrypt()` attempts to encipher `data`. If successful, + * this method attempts to encipher `data`. If successful, * the returned promise is resolved with an `` containing the encrypted result. * * The algorithms currently supported include: * - * - `'RSA-OAEP'` - * - `'AES-CTR'` - * - `'AES-CBC'` - * - `'AES-GCM'` + * * `'AES-CBC'` + * * `'AES-CTR'` + * * `'AES-GCM'` + * * `'AES-OCB'` + * * `'ChaCha20-Poly1305'` + * * `'RSA-OAEP'` * @since v15.0.0 */ encrypt( - algorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AesGcmParams, + algorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AeadParams, key: CryptoKey, data: BufferSource, ): Promise; @@ -4313,35 +5162,47 @@ declare module "crypto" { * * When `format` is `'jwk'` and the export is successful, the returned promise will be resolved with a * JavaScript object conforming to the {@link https://tools.ietf.org/html/rfc7517 JSON Web Key} specification. - * @param format Must be one of `'raw'`, `'pkcs8'`, `'spki'`, or `'jwk'`. + * @param format Must be one of `'raw'`, `'pkcs8'`, `'spki'`, `'jwk'`, `'raw-secret'`, + * `'raw-public'`, or `'raw-seed'`. * @returns `` containing ``. * @since v15.0.0 */ exportKey(format: "jwk", key: CryptoKey): Promise; exportKey(format: Exclude, key: CryptoKey): Promise; /** - * Using the method and parameters provided in `algorithm`, - * `subtle.generateKey()` attempts to generate new keying material. - * Depending the method used, the method may generate either a single `` or a ``. + * Using the parameters provided in `algorithm`, this method + * attempts to generate new keying material. Depending on the algorithm used + * either a single `CryptoKey` or a `CryptoKeyPair` is generated. * - * The `` (public and private key) generating algorithms supported include: + * The `CryptoKeyPair` (public and private key) generating algorithms supported + * include: * - * - `'RSASSA-PKCS1-v1_5'` - * - `'RSA-PSS'` - * - `'RSA-OAEP'` - * - `'ECDSA'` - * - `'Ed25519'` - * - `'Ed448'` - * - `'ECDH'` - * - `'X25519'` - * - `'X448'` - * The `` (secret key) generating algorithms supported include: + * * `'ECDH'` + * * `'ECDSA'` + * * `'Ed25519'` + * * `'Ed448'` + * * `'ML-DSA-44'` + * * `'ML-DSA-65'` + * * `'ML-DSA-87'` + * * `'ML-KEM-512'` + * * `'ML-KEM-768'` + * * `'ML-KEM-1024'` + * * `'RSA-OAEP'` + * * `'RSA-PSS'` + * * `'RSASSA-PKCS1-v1_5'` + * * `'X25519'` + * * `'X448'` * - * - `'HMAC'` - * - `'AES-CTR'` - * - `'AES-CBC'` - * - `'AES-GCM'` - * - `'AES-KW'` + * The `CryptoKey` (secret key) generating algorithms supported include: + * * `'AES-CBC'` + * * `'AES-CTR'` + * * `'AES-GCM'` + * * `'AES-KW'` + * * `'AES-OCB'` + * * `'ChaCha20-Poly1305'` + * * `'HMAC'` + * * `'KMAC128'` + * * `'KMAC256'` * @param keyUsages See {@link https://nodejs.org/docs/latest/api/webcrypto.html#cryptokeyusages Key usages}. * @since v15.0.0 */ @@ -4351,7 +5212,7 @@ declare module "crypto" { keyUsages: readonly KeyUsage[], ): Promise; generateKey( - algorithm: AesKeyGenParams | HmacKeyGenParams | Pbkdf2Params, + algorithm: AesKeyGenParams | HmacKeyGenParams | Pbkdf2Params | KmacKeyGenParams, extractable: boolean, keyUsages: readonly KeyUsage[], ): Promise; @@ -4361,12 +5222,23 @@ declare module "crypto" { keyUsages: KeyUsage[], ): Promise; /** - * The `subtle.importKey()` method attempts to interpret the provided `keyData` as the given `format` - * to create a `` instance using the provided `algorithm`, `extractable`, and `keyUsages` arguments. - * If the import is successful, the returned promise will be resolved with the created ``. + * Derives the public key from a given private key. + * @since v24.7.0 + * @param key A private key from which to derive the corresponding public key. + * @param keyUsages See [Key usages](https://nodejs.org/docs/latest-v24.x/api/webcrypto.html#cryptokeyusages). + * @returns Fulfills with a `CryptoKey` upon success. + */ + getPublicKey(key: CryptoKey, keyUsages: KeyUsage[]): Promise; + /** + * This method attempts to interpret the provided `keyData` + * as the given `format` to create a `CryptoKey` instance using the provided + * `algorithm`, `extractable`, and `keyUsages` arguments. If the import is + * successful, the returned promise will be resolved with a {CryptoKey} + * representation of the key material. * - * If importing a `'PBKDF2'` key, `extractable` must be `false`. - * @param format Must be one of `'raw'`, `'pkcs8'`, `'spki'`, or `'jwk'`. + * If importing KDF algorithm keys, `extractable` must be `false`. + * @param format Must be one of `'raw'`, `'pkcs8'`, `'spki'`, `'jwk'`, `'raw-secret'`, + * `'raw-public'`, or `'raw-seed'`. * @param keyUsages See {@link https://nodejs.org/docs/latest/api/webcrypto.html#cryptokeyusages Key usages}. * @since v15.0.0 */ @@ -4378,7 +5250,8 @@ declare module "crypto" { | RsaHashedImportParams | EcKeyImportParams | HmacImportParams - | AesKeyAlgorithm, + | AesKeyAlgorithm + | KmacImportParams, extractable: boolean, keyUsages: readonly KeyUsage[], ): Promise; @@ -4390,62 +5263,81 @@ declare module "crypto" { | RsaHashedImportParams | EcKeyImportParams | HmacImportParams - | AesKeyAlgorithm, + | AesKeyAlgorithm + | KmacImportParams, extractable: boolean, keyUsages: KeyUsage[], ): Promise; /** * Using the method and parameters given by `algorithm` and the keying material provided by `key`, - * `subtle.sign()` attempts to generate a cryptographic signature of `data`. If successful, + * this method attempts to generate a cryptographic signature of `data`. If successful, * the returned promise is resolved with an `` containing the generated signature. * * The algorithms currently supported include: * - * - `'RSASSA-PKCS1-v1_5'` - * - `'RSA-PSS'` - * - `'ECDSA'` - * - `'Ed25519'` - * - `'Ed448'` - * - `'HMAC'` + * * `'ECDSA'` + * * `'Ed25519'` + * * `'Ed448'` + * * `'HMAC'` + * * `'KMAC128'` + * * `'KMAC256'` + * * `'ML-DSA-44'` + * * `'ML-DSA-65'` + * * `'ML-DSA-87'` + * * `'RSA-PSS'` + * * `'RSASSA-PKCS1-v1_5'` * @since v15.0.0 */ sign( - algorithm: AlgorithmIdentifier | RsaPssParams | EcdsaParams | Ed448Params, + algorithm: AlgorithmIdentifier | RsaPssParams | EcdsaParams | ContextParams | KmacParams, key: CryptoKey, data: BufferSource, ): Promise; /** * In cryptography, "wrapping a key" refers to exporting and then encrypting the keying material. - * The `subtle.unwrapKey()` method attempts to decrypt a wrapped key and create a `` instance. + * This method attempts to decrypt a wrapped key and create a `` instance. * It is equivalent to calling `subtle.decrypt()` first on the encrypted key data (using the `wrappedKey`, `unwrapAlgo`, and `unwrappingKey` arguments as input) * then passing the results in to the `subtle.importKey()` method using the `unwrappedKeyAlgo`, `extractable`, and `keyUsages` arguments as inputs. * If successful, the returned promise is resolved with a `` object. * * The wrapping algorithms currently supported include: * - * - `'RSA-OAEP'` - * - `'AES-CTR'` - * - `'AES-CBC'` - * - `'AES-GCM'` - * - `'AES-KW'` + * * `'AES-CBC'` + * * `'AES-CTR'` + * * `'AES-GCM'` + * * `'AES-KW'` + * * `'AES-OCB'` + * * `'ChaCha20-Poly1305'` + * * `'RSA-OAEP'` * * The unwrapped key algorithms supported include: * - * - `'RSASSA-PKCS1-v1_5'` - * - `'RSA-PSS'` - * - `'RSA-OAEP'` - * - `'ECDSA'` - * - `'Ed25519'` - * - `'Ed448'` - * - `'ECDH'` - * - `'X25519'` - * - `'X448'` - * - `'HMAC'` - * - `'AES-CTR'` - * - `'AES-CBC'` - * - `'AES-GCM'` - * - `'AES-KW'` - * @param format Must be one of `'raw'`, `'pkcs8'`, `'spki'`, or `'jwk'`. + * * `'AES-CBC'` + * * `'AES-CTR'` + * * `'AES-GCM'` + * * `'AES-KW'` + * * `'AES-OCB'` + * * `'ChaCha20-Poly1305'` + * * `'ECDH'` + * * `'ECDSA'` + * * `'Ed25519'` + * * `'Ed448'` + * * `'HMAC'` + * * `'KMAC128'` + * * `'KMAC256'` + * * `'ML-DSA-44'` + * * `'ML-DSA-65'` + * * `'ML-DSA-87'` + * * `'ML-KEM-512'` + * * `'ML-KEM-768'` + * * `'ML-KEM-1024'` + * * `'RSA-OAEP'` + * * `'RSA-PSS'` + * * `'RSASSA-PKCS1-v1_5'` + * * `'X25519'` + * * `'X448'` + * @param format Must be one of `'raw'`, `'pkcs8'`, `'spki'`, `'jwk'`, `'raw-secret'`, + * `'raw-public'`, or `'raw-seed'`. * @param keyUsages See {@link https://nodejs.org/docs/latest/api/webcrypto.html#cryptokeyusages Key usages}. * @since v15.0.0 */ @@ -4453,40 +5345,46 @@ declare module "crypto" { format: KeyFormat, wrappedKey: BufferSource, unwrappingKey: CryptoKey, - unwrapAlgorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AesGcmParams, + unwrapAlgorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AeadParams, unwrappedKeyAlgorithm: | AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams | HmacImportParams - | AesKeyAlgorithm, + | AesKeyAlgorithm + | KmacImportParams, extractable: boolean, keyUsages: KeyUsage[], ): Promise; /** * Using the method and parameters given in `algorithm` and the keying material provided by `key`, - * `subtle.verify()` attempts to verify that `signature` is a valid cryptographic signature of `data`. + * This method attempts to verify that `signature` is a valid cryptographic signature of `data`. * The returned promise is resolved with either `true` or `false`. * * The algorithms currently supported include: * - * - `'RSASSA-PKCS1-v1_5'` - * - `'RSA-PSS'` - * - `'ECDSA'` - * - `'Ed25519'` - * - `'Ed448'` - * - `'HMAC'` + * * `'ECDSA'` + * * `'Ed25519'` + * * `'Ed448'` + * * `'HMAC'` + * * `'KMAC128'` + * * `'KMAC256'` + * * `'ML-DSA-44'` + * * `'ML-DSA-65'` + * * `'ML-DSA-87'` + * * `'RSA-PSS'` + * * `'RSASSA-PKCS1-v1_5'` * @since v15.0.0 */ verify( - algorithm: AlgorithmIdentifier | RsaPssParams | EcdsaParams | Ed448Params, + algorithm: AlgorithmIdentifier | RsaPssParams | EcdsaParams | ContextParams | KmacParams, key: CryptoKey, signature: BufferSource, data: BufferSource, ): Promise; /** * In cryptography, "wrapping a key" refers to exporting and then encrypting the keying material. - * The `subtle.wrapKey()` method exports the keying material into the format identified by `format`, + * This method exports the keying material into the format identified by `format`, * then encrypts it using the method and parameters specified by `wrapAlgo` and the keying material provided by `wrappingKey`. * It is the equivalent to calling `subtle.exportKey()` using `format` and `key` as the arguments, * then passing the result to the `subtle.encrypt()` method using `wrappingKey` and `wrapAlgo` as inputs. @@ -4494,30 +5392,25 @@ declare module "crypto" { * * The wrapping algorithms currently supported include: * - * - `'RSA-OAEP'` - * - `'AES-CTR'` - * - `'AES-CBC'` - * - `'AES-GCM'` - * - `'AES-KW'` - * @param format Must be one of `'raw'`, `'pkcs8'`, `'spki'`, or `'jwk'`. + * * `'AES-CBC'` + * * `'AES-CTR'` + * * `'AES-GCM'` + * * `'AES-KW'` + * * `'AES-OCB'` + * * `'ChaCha20-Poly1305'` + * * `'RSA-OAEP'` + * @param format Must be one of `'raw'`, `'pkcs8'`, `'spki'`, `'jwk'`, `'raw-secret'`, + * `'raw-public'`, or `'raw-seed'`. * @since v15.0.0 */ wrapKey( format: KeyFormat, key: CryptoKey, wrappingKey: CryptoKey, - wrapAlgorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AesGcmParams, + wrapAlgorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AeadParams, ): Promise; } } - - global { - var crypto: typeof globalThis extends { - crypto: infer T; - onmessage: any; - } ? T - : webcrypto.Crypto; - } } declare module "node:crypto" { export * from "crypto"; diff --git a/backend/node_modules/@types/node/dgram.d.ts b/backend/node_modules/@types/node/dgram.d.ts index 3843f23..bc69f0b 100644 --- a/backend/node_modules/@types/node/dgram.d.ts +++ b/backend/node_modules/@types/node/dgram.d.ts @@ -23,10 +23,11 @@ * server.bind(41234); * // Prints: server listening 0.0.0.0:41234 * ``` - * @see [source](https://github.com/nodejs/node/blob/v20.13.1/lib/dgram.js) + * @see [source](https://github.com/nodejs/node/blob/v24.x/lib/dgram.js) */ declare module "dgram" { - import { AddressInfo } from "node:net"; + import { NonSharedBuffer } from "node:buffer"; + import { AddressInfo, BlockList } from "node:net"; import * as dns from "node:dns"; import { Abortable, EventEmitter } from "node:events"; interface RemoteInfo { @@ -45,6 +46,7 @@ declare module "dgram" { interface SocketOptions extends Abortable { type: SocketType; reuseAddr?: boolean | undefined; + reusePort?: boolean | undefined; /** * @default false */ @@ -58,6 +60,8 @@ declare module "dgram" { callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void, ) => void) | undefined; + receiveBlockList?: BlockList | undefined; + sendBlockList?: BlockList | undefined; } /** * Creates a `dgram.Socket` object. Once the socket is created, calling `socket.bind()` will instruct the socket to begin listening for datagram @@ -82,8 +86,8 @@ declare module "dgram" { * @param options Available options are: * @param callback Attached as a listener for `'message'` events. Optional. */ - function createSocket(type: SocketType, callback?: (msg: Buffer, rinfo: RemoteInfo) => void): Socket; - function createSocket(options: SocketOptions, callback?: (msg: Buffer, rinfo: RemoteInfo) => void): Socket; + function createSocket(type: SocketType, callback?: (msg: NonSharedBuffer, rinfo: RemoteInfo) => void): Socket; + function createSocket(options: SocketOptions, callback?: (msg: NonSharedBuffer, rinfo: RemoteInfo) => void): Socket; /** * Encapsulates the datagram functionality. * @@ -352,22 +356,22 @@ declare module "dgram" { * @param callback Called when the message has been sent. */ send( - msg: string | Uint8Array | readonly any[], + msg: string | NodeJS.ArrayBufferView | readonly any[], port?: number, address?: string, callback?: (error: Error | null, bytes: number) => void, ): void; send( - msg: string | Uint8Array | readonly any[], + msg: string | NodeJS.ArrayBufferView | readonly any[], port?: number, callback?: (error: Error | null, bytes: number) => void, ): void; send( - msg: string | Uint8Array | readonly any[], + msg: string | NodeJS.ArrayBufferView | readonly any[], callback?: (error: Error | null, bytes: number) => void, ): void; send( - msg: string | Uint8Array, + msg: string | NodeJS.ArrayBufferView, offset: number, length: number, port?: number, @@ -375,14 +379,14 @@ declare module "dgram" { callback?: (error: Error | null, bytes: number) => void, ): void; send( - msg: string | Uint8Array, + msg: string | NodeJS.ArrayBufferView, offset: number, length: number, port?: number, callback?: (error: Error | null, bytes: number) => void, ): void; send( - msg: string | Uint8Array, + msg: string | NodeJS.ArrayBufferView, offset: number, length: number, callback?: (error: Error | null, bytes: number) => void, @@ -553,37 +557,37 @@ declare module "dgram" { addListener(event: "connect", listener: () => void): this; addListener(event: "error", listener: (err: Error) => void): this; addListener(event: "listening", listener: () => void): this; - addListener(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): this; + addListener(event: "message", listener: (msg: NonSharedBuffer, rinfo: RemoteInfo) => void): this; emit(event: string | symbol, ...args: any[]): boolean; emit(event: "close"): boolean; emit(event: "connect"): boolean; emit(event: "error", err: Error): boolean; emit(event: "listening"): boolean; - emit(event: "message", msg: Buffer, rinfo: RemoteInfo): boolean; + emit(event: "message", msg: NonSharedBuffer, rinfo: RemoteInfo): boolean; on(event: string, listener: (...args: any[]) => void): this; on(event: "close", listener: () => void): this; on(event: "connect", listener: () => void): this; on(event: "error", listener: (err: Error) => void): this; on(event: "listening", listener: () => void): this; - on(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): this; + on(event: "message", listener: (msg: NonSharedBuffer, rinfo: RemoteInfo) => void): this; once(event: string, listener: (...args: any[]) => void): this; once(event: "close", listener: () => void): this; once(event: "connect", listener: () => void): this; once(event: "error", listener: (err: Error) => void): this; once(event: "listening", listener: () => void): this; - once(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): this; + once(event: "message", listener: (msg: NonSharedBuffer, rinfo: RemoteInfo) => void): this; prependListener(event: string, listener: (...args: any[]) => void): this; prependListener(event: "close", listener: () => void): this; prependListener(event: "connect", listener: () => void): this; prependListener(event: "error", listener: (err: Error) => void): this; prependListener(event: "listening", listener: () => void): this; - prependListener(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): this; + prependListener(event: "message", listener: (msg: NonSharedBuffer, rinfo: RemoteInfo) => void): this; prependOnceListener(event: string, listener: (...args: any[]) => void): this; prependOnceListener(event: "close", listener: () => void): this; prependOnceListener(event: "connect", listener: () => void): this; prependOnceListener(event: "error", listener: (err: Error) => void): this; prependOnceListener(event: "listening", listener: () => void): this; - prependOnceListener(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): this; + prependOnceListener(event: "message", listener: (msg: NonSharedBuffer, rinfo: RemoteInfo) => void): this; /** * Calls `socket.close()` and returns a promise that fulfills when the socket has closed. * @since v20.5.0 diff --git a/backend/node_modules/@types/node/diagnostics_channel.d.ts b/backend/node_modules/@types/node/diagnostics_channel.d.ts index e25ca69..025847d 100644 --- a/backend/node_modules/@types/node/diagnostics_channel.d.ts +++ b/backend/node_modules/@types/node/diagnostics_channel.d.ts @@ -20,7 +20,7 @@ * should generally include the module name to avoid collisions with data from * other modules. * @since v15.1.0, v14.17.0 - * @see [source](https://github.com/nodejs/node/blob/v20.13.1/lib/diagnostics_channel.js) + * @see [source](https://github.com/nodejs/node/blob/v24.x/lib/diagnostics_channel.js) */ declare module "diagnostics_channel" { import { AsyncLocalStorage } from "node:async_hooks"; @@ -189,7 +189,6 @@ declare module "diagnostics_channel" { * }); * ``` * @since v15.1.0, v14.17.0 - * @deprecated Since v18.7.0,v16.17.0 - Use {@link subscribe(name, onMessage)} * @param onMessage The handler to receive channel messages */ subscribe(onMessage: ChannelListener): void; @@ -210,7 +209,6 @@ declare module "diagnostics_channel" { * channel.unsubscribe(onMessage); * ``` * @since v15.1.0, v14.17.0 - * @deprecated Since v18.7.0,v16.17.0 - Use {@link unsubscribe(name, onMessage)} * @param onMessage The previous subscribed handler to remove * @return `true` if the handler was found, `false` otherwise. */ @@ -259,7 +257,7 @@ declare module "diagnostics_channel" { * @param store The store to unbind from the channel. * @return `true` if the store was found, `false` otherwise. */ - unbindStore(store: any): void; + unbindStore(store: AsyncLocalStorage): boolean; /** * Applies the given data to any AsyncLocalStorage instances bound to the channel * for the duration of the given function, then publishes to the channel within @@ -297,7 +295,12 @@ declare module "diagnostics_channel" { * @param thisArg The receiver to be used for the function call. * @param args Optional arguments to pass to the function. */ - runStores(): void; + runStores( + context: ContextType, + fn: (this: ThisArg, ...args: Args) => Result, + thisArg?: ThisArg, + ...args: Args + ): Result; } interface TracingChannelSubscribers { start: (message: ContextType) => void; @@ -441,12 +444,12 @@ declare module "diagnostics_channel" { * @param args Optional arguments to pass to the function * @return The return value of the given function */ - traceSync( - fn: (this: ThisArg, ...args: Args) => any, + traceSync( + fn: (this: ThisArg, ...args: Args) => Result, context?: ContextType, thisArg?: ThisArg, ...args: Args - ): void; + ): Result; /** * Trace a promise-returning function call. This will always produce a `start event` and `end event` around the synchronous portion of the * function execution, and will produce an `asyncStart event` and `asyncEnd event` when a promise continuation is reached. It may also @@ -476,12 +479,12 @@ declare module "diagnostics_channel" { * @param args Optional arguments to pass to the function * @return Chained from promise returned by the given function */ - tracePromise( - fn: (this: ThisArg, ...args: Args) => Promise, + tracePromise( + fn: (this: ThisArg, ...args: Args) => Promise, context?: ContextType, thisArg?: ThisArg, ...args: Args - ): void; + ): Promise; /** * Trace a callback-receiving function call. This will always produce a `start event` and `end event` around the synchronous portion of the * function execution, and will produce a `asyncStart event` and `asyncEnd event` around the callback execution. It may also produce an `error event` if the given function throws an error or @@ -540,13 +543,32 @@ declare module "diagnostics_channel" { * @param args Optional arguments to pass to the function * @return The return value of the given function */ - traceCallback any>( - fn: Fn, - position: number | undefined, - context: ContextType | undefined, - thisArg: any, - ...args: Parameters - ): void; + traceCallback( + fn: (this: ThisArg, ...args: Args) => Result, + position?: number, + context?: ContextType, + thisArg?: ThisArg, + ...args: Args + ): Result; + /** + * `true` if any of the individual channels has a subscriber, `false` if not. + * + * This is a helper method available on a {@link TracingChannel} instance to check + * if any of the [TracingChannel Channels](https://nodejs.org/api/diagnostics_channel.html#tracingchannel-channels) have subscribers. + * A `true` is returned if any of them have at least one subscriber, a `false` is returned otherwise. + * + * ```js + * const diagnostics_channel = require('node:diagnostics_channel'); + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * + * if (channels.hasSubscribers) { + * // Do something + * } + * ``` + * @since v22.0.0, v20.13.0 + */ + readonly hasSubscribers: boolean; } } declare module "node:diagnostics_channel" { diff --git a/backend/node_modules/@types/node/dns.d.ts b/backend/node_modules/@types/node/dns.d.ts index f5b6b74..ba0d122 100644 --- a/backend/node_modules/@types/node/dns.d.ts +++ b/backend/node_modules/@types/node/dns.d.ts @@ -9,7 +9,7 @@ * system do, use {@link lookup}. * * ```js - * const dns = require('node:dns'); + * import dns from 'node:dns'; * * dns.lookup('example.org', (err, address, family) => { * console.log('address: %j family: IPv%s', address, family); @@ -23,7 +23,7 @@ * DNS queries, bypassing other name-resolution facilities. * * ```js - * const dns = require('node:dns'); + * import dns from 'node:dns'; * * dns.resolve4('archive.org', (err, addresses) => { * if (err) throw err; @@ -41,8 +41,8 @@ * }); * ``` * - * See the [Implementation considerations section](https://nodejs.org/docs/latest-v20.x/api/dns.html#implementation-considerations) for more information. - * @see [source](https://github.com/nodejs/node/blob/v20.13.1/lib/dns.js) + * See the [Implementation considerations section](https://nodejs.org/docs/latest-v24.x/api/dns.html#implementation-considerations) for more information. + * @see [source](https://github.com/nodejs/node/blob/v24.x/lib/dns.js) */ declare module "dns" { import * as dnsPromises from "node:dns/promises"; @@ -71,7 +71,7 @@ declare module "dns" { */ family?: number | "IPv4" | "IPv6" | undefined; /** - * One or more [supported `getaddrinfo`](https://nodejs.org/docs/latest-v20.x/api/dns.html#supported-getaddrinfo-flags) flags. Multiple flags may be + * One or more [supported `getaddrinfo`](https://nodejs.org/docs/latest-v24.x/api/dns.html#supported-getaddrinfo-flags) flags. Multiple flags may be * passed by bitwise `OR`ing their values. */ hints?: number | undefined; @@ -84,16 +84,17 @@ declare module "dns" { * When `verbatim`, the resolved addresses are return unsorted. When `ipv4first`, the resolved addresses are sorted * by placing IPv4 addresses before IPv6 addresses. When `ipv6first`, the resolved addresses are sorted by placing IPv6 * addresses before IPv4 addresses. Default value is configurable using - * {@link setDefaultResultOrder} or [`--dns-result-order`](https://nodejs.org/docs/latest-v20.x/api/cli.html#--dns-result-orderorder). + * {@link setDefaultResultOrder} or [`--dns-result-order`](https://nodejs.org/docs/latest-v24.x/api/cli.html#--dns-result-orderorder). * @default `verbatim` (addresses are not reordered) + * @since v22.1.0 */ order?: "ipv4first" | "ipv6first" | "verbatim" | undefined; /** * When `true`, the callback receives IPv4 and IPv6 addresses in the order the DNS resolver returned them. When `false`, IPv4 * addresses are placed before IPv6 addresses. This option will be deprecated in favor of `order`. When both are specified, * `order` has higher precedence. New code should only use `order`. Default value is configurable using {@link setDefaultResultOrder} - * or [`--dns-result-order`](https://nodejs.org/docs/latest-v20.x/api/cli.html#--dns-result-orderorder). * @default true (addresses are not reordered) + * @deprecated Please use `order` option */ verbatim?: boolean | undefined; } @@ -132,13 +133,13 @@ declare module "dns" { * The implementation uses an operating system facility that can associate names * with addresses and vice versa. This implementation can have subtle but * important consequences on the behavior of any Node.js program. Please take some - * time to consult the [Implementation considerations section](https://nodejs.org/docs/latest-v20.x/api/dns.html#implementation-considerations) + * time to consult the [Implementation considerations section](https://nodejs.org/docs/latest-v24.x/api/dns.html#implementation-considerations) * before using `dns.lookup()`. * * Example usage: * * ```js - * const dns = require('node:dns'); + * import dns from 'node:dns'; * const options = { * family: 6, * hints: dns.ADDRCONFIG | dns.V4MAPPED, @@ -154,7 +155,7 @@ declare module "dns" { * // addresses: [{"address":"2606:2800:220:1:248:1893:25c8:1946","family":6}] * ``` * - * If this method is invoked as its [util.promisify()](https://nodejs.org/docs/latest-v20.x/api/util.html#utilpromisifyoriginal) ed + * If this method is invoked as its [util.promisify()](https://nodejs.org/docs/latest-v24.x/api/util.html#utilpromisifyoriginal) ed * version, and `all` is not set to `true`, it returns a `Promise` for an `Object` with `address` and `family` properties. * @since v0.1.90 */ @@ -194,18 +195,18 @@ declare module "dns" { * If `address` is not a valid IP address, a `TypeError` will be thrown. * The `port` will be coerced to a number. If it is not a legal port, a `TypeError` will be thrown. * - * On an error, `err` is an [`Error`](https://nodejs.org/docs/latest-v20.x/api/errors.html#class-error) object, + * On an error, `err` is an [`Error`](https://nodejs.org/docs/latest-v24.x/api/errors.html#class-error) object, * where `err.code` is the error code. * * ```js - * const dns = require('node:dns'); + * import dns from 'node:dns'; * dns.lookupService('127.0.0.1', 22, (err, hostname, service) => { * console.log(hostname, service); * // Prints: localhost ssh * }); * ``` * - * If this method is invoked as its [util.promisify()](https://nodejs.org/docs/latest-v20.x/api/util.html#utilpromisifyoriginal) ed + * If this method is invoked as its [util.promisify()](https://nodejs.org/docs/latest-v24.x/api/util.html#utilpromisifyoriginal) ed * version, it returns a `Promise` for an `Object` with `hostname` and `service` properties. * @since v0.11.14 */ @@ -249,6 +250,9 @@ declare module "dns" { contactemail?: string | undefined; contactphone?: string | undefined; } + export interface AnyCaaRecord extends CaaRecord { + type: "CAA"; + } export interface MxRecord { priority: number; exchange: string; @@ -288,6 +292,15 @@ declare module "dns" { export interface AnySrvRecord extends SrvRecord { type: "SRV"; } + export interface TlsaRecord { + certUsage: number; + selector: number; + match: number; + data: ArrayBuffer; + } + export interface AnyTlsaRecord extends TlsaRecord { + type: "TLSA"; + } export interface AnyTxtRecord { type: "TXT"; entries: string[]; @@ -307,6 +320,7 @@ declare module "dns" { export type AnyRecord = | AnyARecord | AnyAaaaRecord + | AnyCaaRecord | AnyCnameRecord | AnyMxRecord | AnyNaptrRecord @@ -314,6 +328,7 @@ declare module "dns" { | AnyPtrRecord | AnySoaRecord | AnySrvRecord + | AnyTlsaRecord | AnyTxtRecord; /** * Uses the DNS protocol to resolve a host name (e.g. `'nodejs.org'`) into an array @@ -322,7 +337,7 @@ declare module "dns" { * * * - * On error, `err` is an [`Error`](https://nodejs.org/docs/latest-v20.x/api/errors.html#class-error) object, + * On error, `err` is an [`Error`](https://nodejs.org/docs/latest-v24.x/api/errors.html#class-error) object, * where `err.code` is one of the `DNS error codes`. * @since v0.1.27 * @param hostname Host name to resolve. @@ -334,12 +349,7 @@ declare module "dns" { ): void; export function resolve( hostname: string, - rrtype: "A", - callback: (err: NodeJS.ErrnoException | null, addresses: string[]) => void, - ): void; - export function resolve( - hostname: string, - rrtype: "AAAA", + rrtype: "A" | "AAAA" | "CNAME" | "NS" | "PTR", callback: (err: NodeJS.ErrnoException | null, addresses: string[]) => void, ): void; export function resolve( @@ -349,8 +359,8 @@ declare module "dns" { ): void; export function resolve( hostname: string, - rrtype: "CNAME", - callback: (err: NodeJS.ErrnoException | null, addresses: string[]) => void, + rrtype: "CAA", + callback: (err: NodeJS.ErrnoException | null, address: CaaRecord[]) => void, ): void; export function resolve( hostname: string, @@ -362,16 +372,6 @@ declare module "dns" { rrtype: "NAPTR", callback: (err: NodeJS.ErrnoException | null, addresses: NaptrRecord[]) => void, ): void; - export function resolve( - hostname: string, - rrtype: "NS", - callback: (err: NodeJS.ErrnoException | null, addresses: string[]) => void, - ): void; - export function resolve( - hostname: string, - rrtype: "PTR", - callback: (err: NodeJS.ErrnoException | null, addresses: string[]) => void, - ): void; export function resolve( hostname: string, rrtype: "SOA", @@ -382,6 +382,11 @@ declare module "dns" { rrtype: "SRV", callback: (err: NodeJS.ErrnoException | null, addresses: SrvRecord[]) => void, ): void; + export function resolve( + hostname: string, + rrtype: "TLSA", + callback: (err: NodeJS.ErrnoException | null, addresses: TlsaRecord[]) => void, + ): void; export function resolve( hostname: string, rrtype: "TXT", @@ -392,21 +397,42 @@ declare module "dns" { rrtype: string, callback: ( err: NodeJS.ErrnoException | null, - addresses: string[] | MxRecord[] | NaptrRecord[] | SoaRecord | SrvRecord[] | string[][] | AnyRecord[], + addresses: + | string[] + | CaaRecord[] + | MxRecord[] + | NaptrRecord[] + | SoaRecord + | SrvRecord[] + | TlsaRecord[] + | string[][] + | AnyRecord[], ) => void, ): void; export namespace resolve { function __promisify__(hostname: string, rrtype?: "A" | "AAAA" | "CNAME" | "NS" | "PTR"): Promise; function __promisify__(hostname: string, rrtype: "ANY"): Promise; + function __promisify__(hostname: string, rrtype: "CAA"): Promise; function __promisify__(hostname: string, rrtype: "MX"): Promise; function __promisify__(hostname: string, rrtype: "NAPTR"): Promise; function __promisify__(hostname: string, rrtype: "SOA"): Promise; function __promisify__(hostname: string, rrtype: "SRV"): Promise; + function __promisify__(hostname: string, rrtype: "TLSA"): Promise; function __promisify__(hostname: string, rrtype: "TXT"): Promise; function __promisify__( hostname: string, rrtype: string, - ): Promise; + ): Promise< + | string[] + | CaaRecord[] + | MxRecord[] + | NaptrRecord[] + | SoaRecord + | SrvRecord[] + | TlsaRecord[] + | string[][] + | AnyRecord[] + >; } /** * Uses the DNS protocol to resolve a IPv4 addresses (`A` records) for the `hostname`. The `addresses` argument passed to the `callback` function @@ -608,6 +634,33 @@ declare module "dns" { export namespace resolveSrv { function __promisify__(hostname: string): Promise; } + /** + * Uses the DNS protocol to resolve certificate associations (`TLSA` records) for + * the `hostname`. The `records` argument passed to the `callback` function is an + * array of objects with these properties: + * + * * `certUsage` + * * `selector` + * * `match` + * * `data` + * + * ```js + * { + * certUsage: 3, + * selector: 1, + * match: 1, + * data: [ArrayBuffer] + * } + * ``` + * @since v23.9.0, v22.15.0 + */ + export function resolveTlsa( + hostname: string, + callback: (err: NodeJS.ErrnoException | null, addresses: TlsaRecord[]) => void, + ): void; + export namespace resolveTlsa { + function __promisify__(hostname: string): Promise; + } /** * Uses the DNS protocol to resolve text queries (`TXT` records) for the `hostname`. The `records` argument passed to the `callback` function is a * two-dimensional array of the text records available for `hostname` (e.g.`[ ['v=spf1 ip4:0.0.0.0 ', '~all' ] ]`). Each sub-array contains TXT chunks of @@ -663,8 +716,8 @@ declare module "dns" { * Performs a reverse DNS query that resolves an IPv4 or IPv6 address to an * array of host names. * - * On error, `err` is an [`Error`](https://nodejs.org/docs/latest-v20.x/api/errors.html#class-error) object, where `err.code` is - * one of the [DNS error codes](https://nodejs.org/docs/latest-v20.x/api/dns.html#error-codes). + * On error, `err` is an [`Error`](https://nodejs.org/docs/latest-v24.x/api/errors.html#class-error) object, where `err.code` is + * one of the [DNS error codes](https://nodejs.org/docs/latest-v24.x/api/dns.html#error-codes). * @since v0.1.16 */ export function reverse( @@ -672,7 +725,7 @@ declare module "dns" { callback: (err: NodeJS.ErrnoException | null, hostnames: string[]) => void, ): void; /** - * Get the default value for `order` in {@link lookup} and [`dnsPromises.lookup()`](https://nodejs.org/docs/latest-v20.x/api/dns.html#dnspromiseslookuphostname-options). + * Get the default value for `order` in {@link lookup} and [`dnsPromises.lookup()`](https://nodejs.org/docs/latest-v24.x/api/dns.html#dnspromiseslookuphostname-options). * The value could be: * * * `ipv4first`: for `order` defaulting to `ipv4first`. @@ -727,7 +780,7 @@ declare module "dns" { */ export function getServers(): string[]; /** - * Set the default value of `order` in {@link lookup} and [`dnsPromises.lookup()`](https://nodejs.org/docs/latest-v20.x/api/dns.html#dnspromiseslookuphostname-options). + * Set the default value of `order` in {@link lookup} and [`dnsPromises.lookup()`](https://nodejs.org/docs/latest-v24.x/api/dns.html#dnspromiseslookuphostname-options). * The value could be: * * * `ipv4first`: sets default `order` to `ipv4first`. @@ -735,8 +788,8 @@ declare module "dns" { * * `verbatim`: sets default `order` to `verbatim`. * * The default is `verbatim` and {@link setDefaultResultOrder} have higher - * priority than [`--dns-result-order`](https://nodejs.org/docs/latest-v20.x/api/cli.html#--dns-result-orderorder). When using - * [worker threads](https://nodejs.org/docs/latest-v20.x/api/worker_threads.html), {@link setDefaultResultOrder} from the main + * priority than [`--dns-result-order`](https://nodejs.org/docs/latest-v24.x/api/cli.html#--dns-result-orderorder). When using + * [worker threads](https://nodejs.org/docs/latest-v24.x/api/worker_threads.html), {@link setDefaultResultOrder} from the main * thread won't affect the default dns orders in workers. * @since v16.4.0, v14.18.0 * @param order must be `'ipv4first'`, `'ipv6first'` or `'verbatim'`. @@ -776,17 +829,22 @@ declare module "dns" { * The number of tries the resolver will try contacting each name server before giving up. * @default 4 */ - tries?: number; + tries?: number | undefined; + /** + * The max retry timeout, in milliseconds. + * @default 0 + */ + maxTimeout?: number | undefined; } /** * An independent resolver for DNS requests. * * Creating a new resolver uses the default server settings. Setting - * the servers used for a resolver using [`resolver.setServers()`](https://nodejs.org/docs/latest-v20.x/api/dns.html#dnssetserversservers) does not affect + * the servers used for a resolver using [`resolver.setServers()`](https://nodejs.org/docs/latest-v24.x/api/dns.html#dnssetserversservers) does not affect * other resolvers: * * ```js - * const { Resolver } = require('node:dns'); + * import { Resolver } from 'node:dns'; * const resolver = new Resolver(); * resolver.setServers(['4.4.4.4']); * @@ -837,6 +895,7 @@ declare module "dns" { resolvePtr: typeof resolvePtr; resolveSoa: typeof resolveSoa; resolveSrv: typeof resolveSrv; + resolveTlsa: typeof resolveTlsa; resolveTxt: typeof resolveTxt; reverse: typeof reverse; /** diff --git a/backend/node_modules/@types/node/dns/promises.d.ts b/backend/node_modules/@types/node/dns/promises.d.ts index cb4c03b..efb9fbf 100644 --- a/backend/node_modules/@types/node/dns/promises.d.ts +++ b/backend/node_modules/@types/node/dns/promises.d.ts @@ -1,7 +1,7 @@ /** * The `dns.promises` API provides an alternative set of asynchronous DNS methods * that return `Promise` objects rather than using callbacks. The API is accessible - * via `require('node:dns').promises` or `require('node:dns/promises')`. + * via `import { promises as dnsPromises } from 'node:dns'` or `import dnsPromises from 'node:dns/promises'`. * @since v10.6.0 */ declare module "dns/promises" { @@ -20,6 +20,7 @@ declare module "dns/promises" { ResolveWithTtlOptions, SoaRecord, SrvRecord, + TlsaRecord, } from "node:dns"; /** * Returns an array of IP address strings, formatted according to [RFC 5952](https://tools.ietf.org/html/rfc5952#section-6), @@ -60,7 +61,7 @@ declare module "dns/promises" { * Example usage: * * ```js - * const dns = require('node:dns'); + * import dns from 'node:dns'; * const dnsPromises = dns.promises; * const options = { * family: 6, @@ -96,7 +97,7 @@ declare module "dns/promises" { * On error, the `Promise` is rejected with an [`Error`](https://nodejs.org/docs/latest-v20.x/api/errors.html#class-error) object, where `err.code` is the error code. * * ```js - * const dnsPromises = require('node:dns').promises; + * import dnsPromises from 'node:dns'; * dnsPromises.lookupService('127.0.0.1', 22).then((result) => { * console.log(result.hostname, result.service); * // Prints: localhost ssh @@ -126,22 +127,26 @@ declare module "dns/promises" { * @param [rrtype='A'] Resource record type. */ function resolve(hostname: string): Promise; - function resolve(hostname: string, rrtype: "A"): Promise; - function resolve(hostname: string, rrtype: "AAAA"): Promise; + function resolve(hostname: string, rrtype: "A" | "AAAA" | "CNAME" | "NS" | "PTR"): Promise; function resolve(hostname: string, rrtype: "ANY"): Promise; function resolve(hostname: string, rrtype: "CAA"): Promise; - function resolve(hostname: string, rrtype: "CNAME"): Promise; function resolve(hostname: string, rrtype: "MX"): Promise; function resolve(hostname: string, rrtype: "NAPTR"): Promise; - function resolve(hostname: string, rrtype: "NS"): Promise; - function resolve(hostname: string, rrtype: "PTR"): Promise; function resolve(hostname: string, rrtype: "SOA"): Promise; function resolve(hostname: string, rrtype: "SRV"): Promise; + function resolve(hostname: string, rrtype: "TLSA"): Promise; function resolve(hostname: string, rrtype: "TXT"): Promise; - function resolve( - hostname: string, - rrtype: string, - ): Promise; + function resolve(hostname: string, rrtype: string): Promise< + | string[] + | CaaRecord[] + | MxRecord[] + | NaptrRecord[] + | SoaRecord + | SrvRecord[] + | TlsaRecord[] + | string[][] + | AnyRecord[] + >; /** * Uses the DNS protocol to resolve IPv4 addresses (`A` records) for the `hostname`. On success, the `Promise` is resolved with an array of IPv4 * addresses (e.g. `['74.125.79.104', '74.125.79.105', '74.125.79.106']`). @@ -292,6 +297,27 @@ declare module "dns/promises" { * @since v10.6.0 */ function resolveSrv(hostname: string): Promise; + /** + * Uses the DNS protocol to resolve certificate associations (`TLSA` records) for + * the `hostname`. On success, the `Promise` is resolved with an array of objectsAdd commentMore actions + * with these properties: + * + * * `certUsage` + * * `selector` + * * `match` + * * `data` + * + * ```js + * { + * certUsage: 3, + * selector: 1, + * match: 1, + * data: [ArrayBuffer] + * } + * ``` + * @since v23.9.0, v22.15.0 + */ + function resolveTlsa(hostname: string): Promise; /** * Uses the DNS protocol to resolve text queries (`TXT` records) for the `hostname`. On success, the `Promise` is resolved with a two-dimensional array * of the text records available for `hostname` (e.g.`[ ['v=spf1 ip4:0.0.0.0 ', '~all' ] ]`). Each sub-array contains TXT chunks of @@ -394,8 +420,8 @@ declare module "dns/promises" { * other resolvers: * * ```js - * const { Resolver } = require('node:dns').promises; - * const resolver = new Resolver(); + * import { promises } from 'node:dns'; + * const resolver = new promises.Resolver(); * resolver.setServers(['4.4.4.4']); * * // This request will use the server at 4.4.4.4, independent of global settings. @@ -450,6 +476,7 @@ declare module "dns/promises" { resolvePtr: typeof resolvePtr; resolveSoa: typeof resolveSoa; resolveSrv: typeof resolveSrv; + resolveTlsa: typeof resolveTlsa; resolveTxt: typeof resolveTxt; reverse: typeof reverse; /** diff --git a/backend/node_modules/@types/node/dom-events.d.ts b/backend/node_modules/@types/node/dom-events.d.ts deleted file mode 100644 index f47f71d..0000000 --- a/backend/node_modules/@types/node/dom-events.d.ts +++ /dev/null @@ -1,124 +0,0 @@ -export {}; // Don't export anything! - -//// DOM-like Events -// NB: The Event / EventTarget / EventListener implementations below were copied -// from lib.dom.d.ts, then edited to reflect Node's documentation at -// https://nodejs.org/api/events.html#class-eventtarget. -// Please read that link to understand important implementation differences. - -// This conditional type will be the existing global Event in a browser, or -// the copy below in a Node environment. -type __Event = typeof globalThis extends { onmessage: any; Event: any } ? {} - : { - /** This is not used in Node.js and is provided purely for completeness. */ - readonly bubbles: boolean; - /** Alias for event.stopPropagation(). This is not used in Node.js and is provided purely for completeness. */ - cancelBubble: () => void; - /** True if the event was created with the cancelable option */ - readonly cancelable: boolean; - /** This is not used in Node.js and is provided purely for completeness. */ - readonly composed: boolean; - /** Returns an array containing the current EventTarget as the only entry or empty if the event is not being dispatched. This is not used in Node.js and is provided purely for completeness. */ - composedPath(): [EventTarget?]; - /** Alias for event.target. */ - readonly currentTarget: EventTarget | null; - /** Is true if cancelable is true and event.preventDefault() has been called. */ - readonly defaultPrevented: boolean; - /** This is not used in Node.js and is provided purely for completeness. */ - readonly eventPhase: 0 | 2; - /** The `AbortSignal` "abort" event is emitted with `isTrusted` set to `true`. The value is `false` in all other cases. */ - readonly isTrusted: boolean; - /** Sets the `defaultPrevented` property to `true` if `cancelable` is `true`. */ - preventDefault(): void; - /** This is not used in Node.js and is provided purely for completeness. */ - returnValue: boolean; - /** Alias for event.target. */ - readonly srcElement: EventTarget | null; - /** Stops the invocation of event listeners after the current one completes. */ - stopImmediatePropagation(): void; - /** This is not used in Node.js and is provided purely for completeness. */ - stopPropagation(): void; - /** The `EventTarget` dispatching the event */ - readonly target: EventTarget | null; - /** The millisecond timestamp when the Event object was created. */ - readonly timeStamp: number; - /** Returns the type of event, e.g. "click", "hashchange", or "submit". */ - readonly type: string; - }; - -// See comment above explaining conditional type -type __EventTarget = typeof globalThis extends { onmessage: any; EventTarget: any } ? {} - : { - /** - * Adds a new handler for the `type` event. Any given `listener` is added only once per `type` and per `capture` option value. - * - * If the `once` option is true, the `listener` is removed after the next time a `type` event is dispatched. - * - * The `capture` option is not used by Node.js in any functional way other than tracking registered event listeners per the `EventTarget` specification. - * Specifically, the `capture` option is used as part of the key when registering a `listener`. - * Any individual `listener` may be added once with `capture = false`, and once with `capture = true`. - */ - addEventListener( - type: string, - listener: EventListener | EventListenerObject, - options?: AddEventListenerOptions | boolean, - ): void; - /** Dispatches a synthetic event event to target and returns true if either event's cancelable attribute value is false or its preventDefault() method was not invoked, and false otherwise. */ - dispatchEvent(event: Event): boolean; - /** Removes the event listener in target's event listener list with the same type, callback, and options. */ - removeEventListener( - type: string, - listener: EventListener | EventListenerObject, - options?: EventListenerOptions | boolean, - ): void; - }; - -interface EventInit { - bubbles?: boolean; - cancelable?: boolean; - composed?: boolean; -} - -interface EventListenerOptions { - /** Not directly used by Node.js. Added for API completeness. Default: `false`. */ - capture?: boolean; -} - -interface AddEventListenerOptions extends EventListenerOptions { - /** When `true`, the listener is automatically removed when it is first invoked. Default: `false`. */ - once?: boolean; - /** When `true`, serves as a hint that the listener will not call the `Event` object's `preventDefault()` method. Default: false. */ - passive?: boolean; - /** The listener will be removed when the given AbortSignal object's `abort()` method is called. */ - signal?: AbortSignal; -} - -interface EventListener { - (evt: Event): void; -} - -interface EventListenerObject { - handleEvent(object: Event): void; -} - -import {} from "events"; // Make this an ambient declaration -declare global { - /** An event which takes place in the DOM. */ - interface Event extends __Event {} - var Event: typeof globalThis extends { onmessage: any; Event: infer T } ? T - : { - prototype: __Event; - new(type: string, eventInitDict?: EventInit): __Event; - }; - - /** - * EventTarget is a DOM interface implemented by objects that can - * receive events and may have listeners for them. - */ - interface EventTarget extends __EventTarget {} - var EventTarget: typeof globalThis extends { onmessage: any; EventTarget: infer T } ? T - : { - prototype: __EventTarget; - new(): __EventTarget; - }; -} diff --git a/backend/node_modules/@types/node/domain.d.ts b/backend/node_modules/@types/node/domain.d.ts index d8bc999..4c64115 100644 --- a/backend/node_modules/@types/node/domain.d.ts +++ b/backend/node_modules/@types/node/domain.d.ts @@ -12,7 +12,7 @@ * will be notified, rather than losing the context of the error in the `process.on('uncaughtException')` handler, or causing the program to * exit immediately with an error code. * @deprecated Since v1.4.2 - Deprecated - * @see [source](https://github.com/nodejs/node/blob/v20.13.1/lib/domain.js) + * @see [source](https://github.com/nodejs/node/blob/v24.x/lib/domain.js) */ declare module "domain" { import EventEmitter = require("node:events"); @@ -63,8 +63,8 @@ declare module "domain" { * This is the most basic way to use a domain. * * ```js - * const domain = require('node:domain'); - * const fs = require('node:fs'); + * import domain from 'node:domain'; + * import fs from 'node:fs'; * const d = domain.create(); * d.on('error', (er) => { * console.error('Caught error!', er); diff --git a/backend/node_modules/@types/node/events.d.ts b/backend/node_modules/@types/node/events.d.ts index e7c2341..023348e 100644 --- a/backend/node_modules/@types/node/events.d.ts +++ b/backend/node_modules/@types/node/events.d.ts @@ -32,43 +32,10 @@ * }); * myEmitter.emit('event'); * ``` - * @see [source](https://github.com/nodejs/node/blob/v20.13.1/lib/events.js) + * @see [source](https://github.com/nodejs/node/blob/v24.x/lib/events.js) */ declare module "events" { import { AsyncResource, AsyncResourceOptions } from "node:async_hooks"; - // NOTE: This class is in the docs but is **not actually exported** by Node. - // If https://github.com/nodejs/node/issues/39903 gets resolved and Node - // actually starts exporting the class, uncomment below. - // import { EventListener, EventListenerObject } from '__dom-events'; - // /** The NodeEventTarget is a Node.js-specific extension to EventTarget that emulates a subset of the EventEmitter API. */ - // interface NodeEventTarget extends EventTarget { - // /** - // * Node.js-specific extension to the `EventTarget` class that emulates the equivalent `EventEmitter` API. - // * The only difference between `addListener()` and `addEventListener()` is that addListener() will return a reference to the EventTarget. - // */ - // addListener(type: string, listener: EventListener | EventListenerObject, options?: { once: boolean }): this; - // /** Node.js-specific extension to the `EventTarget` class that returns an array of event `type` names for which event listeners are registered. */ - // eventNames(): string[]; - // /** Node.js-specific extension to the `EventTarget` class that returns the number of event listeners registered for the `type`. */ - // listenerCount(type: string): number; - // /** Node.js-specific alias for `eventTarget.removeListener()`. */ - // off(type: string, listener: EventListener | EventListenerObject): this; - // /** Node.js-specific alias for `eventTarget.addListener()`. */ - // on(type: string, listener: EventListener | EventListenerObject, options?: { once: boolean }): this; - // /** Node.js-specific extension to the `EventTarget` class that adds a `once` listener for the given event `type`. This is equivalent to calling `on` with the `once` option set to `true`. */ - // once(type: string, listener: EventListener | EventListenerObject): this; - // /** - // * Node.js-specific extension to the `EventTarget` class. - // * If `type` is specified, removes all registered listeners for `type`, - // * otherwise removes all registered listeners. - // */ - // removeAllListeners(type: string): this; - // /** - // * Node.js-specific extension to the `EventTarget` class that removes the listener for the given `type`. - // * The only difference between `removeListener()` and `removeEventListener()` is that `removeListener()` will return a reference to the `EventTarget`. - // */ - // removeListener(type: string, listener: EventListener | EventListenerObject): this; - // } interface EventEmitterOptions { /** * Enables automatic capturing of promise rejection. @@ -304,12 +271,12 @@ declare module "events" { emitter: NodeJS.EventEmitter, eventName: string | symbol, options?: StaticEventEmitterIteratorOptions, - ): AsyncIterableIterator; + ): NodeJS.AsyncIterator; static on( emitter: EventTarget, eventName: string, options?: StaticEventEmitterIteratorOptions, - ): AsyncIterableIterator; + ): NodeJS.AsyncIterator; /** * A class method that returns the number of listeners for the given `eventName` registered on the given `emitter`. * @@ -396,7 +363,7 @@ declare module "events" { * ``` * @since v15.4.0 * @param n A non-negative number. The maximum number of listeners per `EventTarget` event. - * @param eventsTargets Zero or more {EventTarget} or {EventEmitter} instances. If none are specified, `n` is set as the default max for all newly created {EventTarget} and {EventEmitter} + * @param eventTargets Zero or more {EventTarget} or {EventEmitter} instances. If none are specified, `n` is set as the default max for all newly created {EventTarget} and {EventEmitter} * objects. */ static setMaxListeners(n?: number, ...eventTargets: Array): void; @@ -431,7 +398,6 @@ declare module "events" { * } * ``` * @since v20.5.0 - * @experimental * @return Disposable that removes the `abort` listener. */ static addAbortListener(signal: AbortSignal, resource: (event: Event) => void): Disposable; @@ -518,7 +484,7 @@ declare module "events" { * directly rather than as a child class. * @default new.target.name if instantiated as a child class. */ - name?: string; + name?: string | undefined; } /** @@ -585,6 +551,85 @@ declare module "events" { */ readonly asyncResource: EventEmitterReferencingAsyncResource; } + /** + * The `NodeEventTarget` is a Node.js-specific extension to `EventTarget` + * that emulates a subset of the `EventEmitter` API. + * @since v14.5.0 + */ + export interface NodeEventTarget extends EventTarget { + /** + * Node.js-specific extension to the `EventTarget` class that emulates the + * equivalent `EventEmitter` API. The only difference between `addListener()` and + * `addEventListener()` is that `addListener()` will return a reference to the + * `EventTarget`. + * @since v14.5.0 + */ + addListener(type: string, listener: (arg: any) => void): this; + /** + * Node.js-specific extension to the `EventTarget` class that dispatches the + * `arg` to the list of handlers for `type`. + * @since v15.2.0 + * @returns `true` if event listeners registered for the `type` exist, + * otherwise `false`. + */ + emit(type: string, arg: any): boolean; + /** + * Node.js-specific extension to the `EventTarget` class that returns an array + * of event `type` names for which event listeners are registered. + * @since 14.5.0 + */ + eventNames(): string[]; + /** + * Node.js-specific extension to the `EventTarget` class that returns the number + * of event listeners registered for the `type`. + * @since v14.5.0 + */ + listenerCount(type: string): number; + /** + * Node.js-specific extension to the `EventTarget` class that sets the number + * of max event listeners as `n`. + * @since v14.5.0 + */ + setMaxListeners(n: number): void; + /** + * Node.js-specific extension to the `EventTarget` class that returns the number + * of max event listeners. + * @since v14.5.0 + */ + getMaxListeners(): number; + /** + * Node.js-specific alias for `eventTarget.removeEventListener()`. + * @since v14.5.0 + */ + off(type: string, listener: (arg: any) => void, options?: EventListenerOptions): this; + /** + * Node.js-specific alias for `eventTarget.addEventListener()`. + * @since v14.5.0 + */ + on(type: string, listener: (arg: any) => void): this; + /** + * Node.js-specific extension to the `EventTarget` class that adds a `once` + * listener for the given event `type`. This is equivalent to calling `on` + * with the `once` option set to `true`. + * @since v14.5.0 + */ + once(type: string, listener: (arg: any) => void): this; + /** + * Node.js-specific extension to the `EventTarget` class. If `type` is specified, + * removes all registered listeners for `type`, otherwise removes all registered + * listeners. + * @since v14.5.0 + */ + removeAllListeners(type?: string): this; + /** + * Node.js-specific extension to the `EventTarget` class that removes the + * `listener` for the given `type`. The only difference between `removeListener()` + * and `removeEventListener()` is that `removeListener()` will return a reference + * to the `EventTarget`. + * @since v14.5.0 + */ + removeListener(type: string, listener: (arg: any) => void, options?: EventListenerOptions): this; + } } global { namespace NodeJS { @@ -768,7 +813,7 @@ declare module "events" { setMaxListeners(n: number): this; /** * Returns the current max listener value for the `EventEmitter` which is either - * set by `emitter.setMaxListeners(n)` or defaults to {@link defaultMaxListeners}. + * set by `emitter.setMaxListeners(n)` or defaults to {@link EventEmitter.defaultMaxListeners}. * @since v1.0.0 */ getMaxListeners(): number; diff --git a/backend/node_modules/@types/node/fs.d.ts b/backend/node_modules/@types/node/fs.d.ts index dc1d5da..b300ca4 100644 --- a/backend/node_modules/@types/node/fs.d.ts +++ b/backend/node_modules/@types/node/fs.d.ts @@ -16,9 +16,10 @@ * * All file system operations have synchronous, callback, and promise-based * forms, and are accessible using both CommonJS syntax and ES6 Modules (ESM). - * @see [source](https://github.com/nodejs/node/blob/v20.13.1/lib/fs.js) + * @see [source](https://github.com/nodejs/node/blob/v24.x/lib/fs.js) */ declare module "fs" { + import { NonSharedBuffer } from "node:buffer"; import * as stream from "node:stream"; import { Abortable, EventEmitter } from "node:events"; import { URL } from "node:url"; @@ -130,7 +131,9 @@ declare module "fs" { * ``` * @since v0.1.21 */ - export class Stats {} + export class Stats { + private constructor(); + } export interface StatsFsBase { /** Type of file system. */ type: T; @@ -196,7 +199,7 @@ declare module "fs" { * the `withFileTypes` option set to `true`, the resulting array is filled with `fs.Dirent` objects, rather than strings or `Buffer` s. * @since v10.10.0 */ - export class Dirent { + export class Dirent { /** * Returns `true` if the `fs.Dirent` object describes a regular file. * @since v10.10.0 @@ -239,18 +242,12 @@ declare module "fs" { * value is determined by the `options.encoding` passed to {@link readdir} or {@link readdirSync}. * @since v10.10.0 */ - name: string; + name: Name; /** - * The base path that this `fs.Dirent` object refers to. - * @since v20.12.0 + * The path to the parent directory of the file this `fs.Dirent` object refers to. + * @since v20.12.0, v18.20.0 */ parentPath: string; - /** - * Alias for `dirent.parentPath`. - * @since v20.1.0 - * @deprecated Since v20.12.0 - */ - path: string; } /** * A class representing a directory stream. @@ -282,7 +279,7 @@ declare module "fs" { /** * Asynchronously iterates over the directory via `readdir(3)` until all entries have been read. */ - [Symbol.asyncIterator](): AsyncIterableIterator; + [Symbol.asyncIterator](): NodeJS.AsyncIterator; /** * Asynchronously close the directory's underlying resource handle. * Subsequent reads will result in errors. @@ -326,6 +323,18 @@ declare module "fs" { * @since v12.12.0 */ readSync(): Dirent | null; + /** + * Calls `dir.close()` if the directory handle is open, and returns a promise that + * fulfills when disposal is complete. + * @since v24.1.0 + */ + [Symbol.asyncDispose](): Promise; + /** + * Calls `dir.closeSync()` if the directory handle is open, and returns + * `undefined`. + * @since v24.1.0 + */ + [Symbol.dispose](): void; } /** * Class: fs.StatWatcher @@ -386,23 +395,29 @@ declare module "fs" { * 3. error */ addListener(event: string, listener: (...args: any[]) => void): this; - addListener(event: "change", listener: (eventType: string, filename: string | Buffer) => void): this; + addListener(event: "change", listener: (eventType: string, filename: string | NonSharedBuffer) => void): this; addListener(event: "close", listener: () => void): this; addListener(event: "error", listener: (error: Error) => void): this; on(event: string, listener: (...args: any[]) => void): this; - on(event: "change", listener: (eventType: string, filename: string | Buffer) => void): this; + on(event: "change", listener: (eventType: string, filename: string | NonSharedBuffer) => void): this; on(event: "close", listener: () => void): this; on(event: "error", listener: (error: Error) => void): this; once(event: string, listener: (...args: any[]) => void): this; - once(event: "change", listener: (eventType: string, filename: string | Buffer) => void): this; + once(event: "change", listener: (eventType: string, filename: string | NonSharedBuffer) => void): this; once(event: "close", listener: () => void): this; once(event: "error", listener: (error: Error) => void): this; prependListener(event: string, listener: (...args: any[]) => void): this; - prependListener(event: "change", listener: (eventType: string, filename: string | Buffer) => void): this; + prependListener( + event: "change", + listener: (eventType: string, filename: string | NonSharedBuffer) => void, + ): this; prependListener(event: "close", listener: () => void): this; prependListener(event: "error", listener: (error: Error) => void): this; prependOnceListener(event: string, listener: (...args: any[]) => void): this; - prependOnceListener(event: "change", listener: (eventType: string, filename: string | Buffer) => void): this; + prependOnceListener( + event: "change", + listener: (eventType: string, filename: string | NonSharedBuffer) => void, + ): this; prependOnceListener(event: "close", listener: () => void): this; prependOnceListener(event: "error", listener: (error: Error) => void): this; } @@ -436,57 +451,271 @@ declare module "fs" { * 2. close * 3. ready */ - addListener(event: "close", listener: () => void): this; - addListener(event: "data", listener: (chunk: Buffer | string) => void): this; - addListener(event: "end", listener: () => void): this; - addListener(event: "error", listener: (err: Error) => void): this; - addListener(event: "open", listener: (fd: number) => void): this; - addListener(event: "pause", listener: () => void): this; - addListener(event: "readable", listener: () => void): this; - addListener(event: "ready", listener: () => void): this; - addListener(event: "resume", listener: () => void): this; - addListener(event: string | symbol, listener: (...args: any[]) => void): this; - on(event: "close", listener: () => void): this; - on(event: "data", listener: (chunk: Buffer | string) => void): this; - on(event: "end", listener: () => void): this; - on(event: "error", listener: (err: Error) => void): this; - on(event: "open", listener: (fd: number) => void): this; - on(event: "pause", listener: () => void): this; - on(event: "readable", listener: () => void): this; - on(event: "ready", listener: () => void): this; - on(event: "resume", listener: () => void): this; - on(event: string | symbol, listener: (...args: any[]) => void): this; - once(event: "close", listener: () => void): this; - once(event: "data", listener: (chunk: Buffer | string) => void): this; - once(event: "end", listener: () => void): this; - once(event: "error", listener: (err: Error) => void): this; - once(event: "open", listener: (fd: number) => void): this; - once(event: "pause", listener: () => void): this; - once(event: "readable", listener: () => void): this; - once(event: "ready", listener: () => void): this; - once(event: "resume", listener: () => void): this; - once(event: string | symbol, listener: (...args: any[]) => void): this; - prependListener(event: "close", listener: () => void): this; - prependListener(event: "data", listener: (chunk: Buffer | string) => void): this; - prependListener(event: "end", listener: () => void): this; - prependListener(event: "error", listener: (err: Error) => void): this; - prependListener(event: "open", listener: (fd: number) => void): this; - prependListener(event: "pause", listener: () => void): this; - prependListener(event: "readable", listener: () => void): this; - prependListener(event: "ready", listener: () => void): this; - prependListener(event: "resume", listener: () => void): this; - prependListener(event: string | symbol, listener: (...args: any[]) => void): this; - prependOnceListener(event: "close", listener: () => void): this; - prependOnceListener(event: "data", listener: (chunk: Buffer | string) => void): this; - prependOnceListener(event: "end", listener: () => void): this; - prependOnceListener(event: "error", listener: (err: Error) => void): this; - prependOnceListener(event: "open", listener: (fd: number) => void): this; - prependOnceListener(event: "pause", listener: () => void): this; - prependOnceListener(event: "readable", listener: () => void): this; - prependOnceListener(event: "ready", listener: () => void): this; - prependOnceListener(event: "resume", listener: () => void): this; - prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; + addListener(event: K, listener: ReadStreamEvents[K]): this; + on(event: K, listener: ReadStreamEvents[K]): this; + once(event: K, listener: ReadStreamEvents[K]): this; + prependListener(event: K, listener: ReadStreamEvents[K]): this; + prependOnceListener(event: K, listener: ReadStreamEvents[K]): this; } + export interface Utf8StreamOptions { + /** + * Appends writes to dest file instead of truncating it. + * @default true + */ + append?: boolean | undefined; + /** + * Which type of data you can send to the write + * function, supported values are `'utf8'` or `'buffer'`. + * @default 'utf8' + */ + contentMode?: "utf8" | "buffer" | undefined; + /** + * A path to a file to be written to (mode controlled by the + * append option). + */ + dest?: string | undefined; + /** + * A file descriptor, something that is returned by `fs.open()` + * or `fs.openSync()`. + */ + fd?: number | undefined; + /** + * An object that has the same API as the `fs` module, useful + * for mocking, testing, or customizing the behavior of the stream. + */ + fs?: object | undefined; + /** + * Perform a `fs.fsyncSync()` every time a write is + * completed. + */ + fsync?: boolean | undefined; + /** + * The maximum length of the internal buffer. If a write + * operation would cause the buffer to exceed `maxLength`, the data written is + * dropped and a drop event is emitted with the dropped data + */ + maxLength?: number | undefined; + /** + * The maximum number of bytes that can be written; + * @default 16384 + */ + maxWrite?: number | undefined; + /** + * The minimum length of the internal buffer that is + * required to be full before flushing. + */ + minLength?: number | undefined; + /** + * Ensure directory for `dest` file exists when true. + * @default false + */ + mkdir?: boolean | undefined; + /** + * Specify the creating file mode (see `fs.open()`). + */ + mode?: number | string | undefined; + /** + * Calls flush every `periodicFlush` milliseconds. + */ + periodicFlush?: number | undefined; + /** + * A function that will be called when `write()`, + * `writeSync()`, or `flushSync()` encounters an `EAGAIN` or `EBUSY` error. + * If the return value is `true` the operation will be retried, otherwise it + * will bubble the error. The `err` is the error that caused this function to + * be called, `writeBufferLen` is the length of the buffer that was written, + * and `remainingBufferLen` is the length of the remaining buffer that the + * stream did not try to write. + */ + retryEAGAIN?: ((err: Error | null, writeBufferLen: number, remainingBufferLen: number) => boolean) | undefined; + /** + * Perform writes synchronously. + */ + sync?: boolean | undefined; + } + /** + * An optimized UTF-8 stream writer that allows for flushing all the internal + * buffering on demand. It handles `EAGAIN` errors correctly, allowing for + * customization, for example, by dropping content if the disk is busy. + * @since v24.6.0 + * @experimental + */ + export class Utf8Stream extends EventEmitter { + constructor(options: Utf8StreamOptions); + /** + * Whether the stream is appending to the file or truncating it. + */ + readonly append: boolean; + /** + * The type of data that can be written to the stream. Supported + * values are `'utf8'` or `'buffer'`. + * @default 'utf8' + */ + readonly contentMode: "utf8" | "buffer"; + /** + * Close the stream immediately, without flushing the internal buffer. + */ + destroy(): void; + /** + * Close the stream gracefully, flushing the internal buffer before closing. + */ + end(): void; + /** + * The file descriptor that is being written to. + */ + readonly fd: number; + /** + * The file that is being written to. + */ + readonly file: string; + /** + * Writes the current buffer to the file if a write was not in progress. Do + * nothing if `minLength` is zero or if it is already writing. + */ + flush(callback: (err: Error | null) => void): void; + /** + * Flushes the buffered data synchronously. This is a costly operation. + */ + flushSync(): void; + /** + * Whether the stream is performing a `fs.fsyncSync()` after every + * write operation. + */ + readonly fsync: boolean; + /** + * The maximum length of the internal buffer. If a write + * operation would cause the buffer to exceed `maxLength`, the data written is + * dropped and a drop event is emitted with the dropped data. + */ + readonly maxLength: number; + /** + * The minimum length of the internal buffer that is required to be + * full before flushing. + */ + readonly minLength: number; + /** + * Whether the stream should ensure that the directory for the + * `dest` file exists. If `true`, it will create the directory if it does not + * exist. + * @default false + */ + readonly mkdir: boolean; + /** + * The mode of the file that is being written to. + */ + readonly mode: number | string; + /** + * The number of milliseconds between flushes. If set to `0`, no + * periodic flushes will be performed. + */ + readonly periodicFlush: number; + /** + * Reopen the file in place, useful for log rotation. + * @param file A path to a file to be written to (mode + * controlled by the append option). + */ + reopen(file: PathLike): void; + /** + * Whether the stream is writing synchronously or asynchronously. + */ + readonly sync: boolean; + /** + * When the `options.contentMode` is set to `'utf8'` when the stream is created, + * the `data` argument must be a string. If the `contentMode` is set to `'buffer'`, + * the `data` argument must be a `Buffer`. + * @param data The data to write. + */ + write(data: string | Buffer): boolean; + /** + * Whether the stream is currently writing data to the file. + */ + readonly writing: boolean; + /** + * Calls `utf8Stream.destroy()`. + */ + [Symbol.dispose](): void; + /** + * events.EventEmitter + * 1. change + * 2. close + * 3. error + */ + addListener(event: "close", listener: () => void): this; + addListener(event: "drain", listener: () => void): this; + addListener(event: "drop", listener: (data: string | Buffer) => void): this; + addListener(event: "error", listener: (error: Error) => void): this; + addListener(event: "finish", listener: () => void): this; + addListener(event: "ready", listener: () => void): this; + addListener(event: "write", listener: (n: number) => void): this; + addListener(event: string, listener: (...args: any[]) => void): this; + on(event: "close", listener: () => void): this; + on(event: "drain", listener: () => void): this; + on(event: "drop", listener: (data: string | Buffer) => void): this; + on(event: "error", listener: (error: Error) => void): this; + on(event: "finish", listener: () => void): this; + on(event: "ready", listener: () => void): this; + on(event: "write", listener: (n: number) => void): this; + on(event: string, listener: (...args: any[]) => void): this; + once(event: "close", listener: () => void): this; + once(event: "drain", listener: () => void): this; + once(event: "drop", listener: (data: string | Buffer) => void): this; + once(event: "error", listener: (error: Error) => void): this; + once(event: "finish", listener: () => void): this; + once(event: "ready", listener: () => void): this; + once(event: "write", listener: (n: number) => void): this; + once(event: string, listener: (...args: any[]) => void): this; + prependListener(event: "close", listener: () => void): this; + prependListener(event: "drain", listener: () => void): this; + prependListener(event: "drop", listener: (data: string | Buffer) => void): this; + prependListener(event: "error", listener: (error: Error) => void): this; + prependListener(event: "finish", listener: () => void): this; + prependListener(event: "ready", listener: () => void): this; + prependListener(event: "write", listener: (n: number) => void): this; + prependListener(event: string, listener: (...args: any[]) => void): this; + prependOnceListener(event: "close", listener: () => void): this; + prependOnceListener(event: "drain", listener: () => void): this; + prependOnceListener(event: "drop", listener: (data: string | Buffer) => void): this; + prependOnceListener(event: "error", listener: (error: Error) => void): this; + prependOnceListener(event: "finish", listener: () => void): this; + prependOnceListener(event: "ready", listener: () => void): this; + prependOnceListener(event: "write", listener: (n: number) => void): this; + prependOnceListener(event: string, listener: (...args: any[]) => void): this; + } + + /** + * The Keys are events of the ReadStream and the values are the functions that are called when the event is emitted. + */ + type ReadStreamEvents = { + close: () => void; + data: (chunk: Buffer | string) => void; + end: () => void; + error: (err: Error) => void; + open: (fd: number) => void; + pause: () => void; + readable: () => void; + ready: () => void; + resume: () => void; + } & CustomEvents; + + /** + * string & {} allows to allow any kind of strings for the event + * but still allows to have auto completion for the normal events. + */ + type CustomEvents = { [Key in string & {} | symbol]: (...args: any[]) => void }; + + /** + * The Keys are events of the WriteStream and the values are the functions that are called when the event is emitted. + */ + type WriteStreamEvents = { + close: () => void; + drain: () => void; + error: (err: Error) => void; + finish: () => void; + open: (fd: number) => void; + pipe: (src: stream.Readable) => void; + ready: () => void; + unpipe: (src: stream.Readable) => void; + } & CustomEvents; /** * * Extends `stream.Writable` * @@ -525,51 +754,11 @@ declare module "fs" { * 2. close * 3. ready */ - addListener(event: "close", listener: () => void): this; - addListener(event: "drain", listener: () => void): this; - addListener(event: "error", listener: (err: Error) => void): this; - addListener(event: "finish", listener: () => void): this; - addListener(event: "open", listener: (fd: number) => void): this; - addListener(event: "pipe", listener: (src: stream.Readable) => void): this; - addListener(event: "ready", listener: () => void): this; - addListener(event: "unpipe", listener: (src: stream.Readable) => void): this; - addListener(event: string | symbol, listener: (...args: any[]) => void): this; - on(event: "close", listener: () => void): this; - on(event: "drain", listener: () => void): this; - on(event: "error", listener: (err: Error) => void): this; - on(event: "finish", listener: () => void): this; - on(event: "open", listener: (fd: number) => void): this; - on(event: "pipe", listener: (src: stream.Readable) => void): this; - on(event: "ready", listener: () => void): this; - on(event: "unpipe", listener: (src: stream.Readable) => void): this; - on(event: string | symbol, listener: (...args: any[]) => void): this; - once(event: "close", listener: () => void): this; - once(event: "drain", listener: () => void): this; - once(event: "error", listener: (err: Error) => void): this; - once(event: "finish", listener: () => void): this; - once(event: "open", listener: (fd: number) => void): this; - once(event: "pipe", listener: (src: stream.Readable) => void): this; - once(event: "ready", listener: () => void): this; - once(event: "unpipe", listener: (src: stream.Readable) => void): this; - once(event: string | symbol, listener: (...args: any[]) => void): this; - prependListener(event: "close", listener: () => void): this; - prependListener(event: "drain", listener: () => void): this; - prependListener(event: "error", listener: (err: Error) => void): this; - prependListener(event: "finish", listener: () => void): this; - prependListener(event: "open", listener: (fd: number) => void): this; - prependListener(event: "pipe", listener: (src: stream.Readable) => void): this; - prependListener(event: "ready", listener: () => void): this; - prependListener(event: "unpipe", listener: (src: stream.Readable) => void): this; - prependListener(event: string | symbol, listener: (...args: any[]) => void): this; - prependOnceListener(event: "close", listener: () => void): this; - prependOnceListener(event: "drain", listener: () => void): this; - prependOnceListener(event: "error", listener: (err: Error) => void): this; - prependOnceListener(event: "finish", listener: () => void): this; - prependOnceListener(event: "open", listener: (fd: number) => void): this; - prependOnceListener(event: "pipe", listener: (src: stream.Readable) => void): this; - prependOnceListener(event: "ready", listener: () => void): this; - prependOnceListener(event: "unpipe", listener: (src: stream.Readable) => void): this; - prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; + addListener(event: K, listener: WriteStreamEvents[K]): this; + on(event: K, listener: WriteStreamEvents[K]): this; + once(event: K, listener: WriteStreamEvents[K]): this; + prependListener(event: K, listener: WriteStreamEvents[K]): this; + prependOnceListener(event: K, listener: WriteStreamEvents[K]): this; } /** * Asynchronously rename file at `oldPath` to the pathname provided @@ -629,7 +818,7 @@ declare module "fs" { * @since v0.8.6 * @param [len=0] */ - export function truncate(path: PathLike, len: number | undefined | null, callback: NoParamCallback): void; + export function truncate(path: PathLike, len: number | undefined, callback: NoParamCallback): void; /** * Asynchronous truncate(2) - Truncate a file to a specified length. * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. @@ -641,7 +830,7 @@ declare module "fs" { * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. * @param len If not specified, defaults to `0`. */ - function __promisify__(path: PathLike, len?: number | null): Promise; + function __promisify__(path: PathLike, len?: number): Promise; } /** * Truncates the file. Returns `undefined`. A file descriptor can also be @@ -652,7 +841,7 @@ declare module "fs" { * @since v0.8.6 * @param [len=0] */ - export function truncateSync(path: PathLike, len?: number | null): void; + export function truncateSync(path: PathLike, len?: number): void; /** * Truncates the file descriptor. No arguments other than a possible exception are * given to the completion callback. @@ -696,7 +885,7 @@ declare module "fs" { * @since v0.8.6 * @param [len=0] */ - export function ftruncate(fd: number, len: number | undefined | null, callback: NoParamCallback): void; + export function ftruncate(fd: number, len: number | undefined, callback: NoParamCallback): void; /** * Asynchronous ftruncate(2) - Truncate a file to a specified length. * @param fd A file descriptor. @@ -708,7 +897,7 @@ declare module "fs" { * @param fd A file descriptor. * @param len If not specified, defaults to `0`. */ - function __promisify__(fd: number, len?: number | null): Promise; + function __promisify__(fd: number, len?: number): Promise; } /** * Truncates the file descriptor. Returns `undefined`. @@ -718,7 +907,7 @@ declare module "fs" { * @since v0.8.6 * @param [len=0] */ - export function ftruncateSync(fd: number, len?: number | null): void; + export function ftruncateSync(fd: number, len?: number): void; /** * Asynchronously changes owner and group of a file. No arguments other than a * possible exception are given to the completion callback. @@ -1368,7 +1557,7 @@ declare module "fs" { export function readlink( path: PathLike, options: BufferEncodingOption, - callback: (err: NodeJS.ErrnoException | null, linkString: Buffer) => void, + callback: (err: NodeJS.ErrnoException | null, linkString: NonSharedBuffer) => void, ): void; /** * Asynchronous readlink(2) - read value of a symbolic link. @@ -1378,7 +1567,7 @@ declare module "fs" { export function readlink( path: PathLike, options: EncodingOption, - callback: (err: NodeJS.ErrnoException | null, linkString: string | Buffer) => void, + callback: (err: NodeJS.ErrnoException | null, linkString: string | NonSharedBuffer) => void, ): void; /** * Asynchronous readlink(2) - read value of a symbolic link. @@ -1400,13 +1589,13 @@ declare module "fs" { * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. */ - function __promisify__(path: PathLike, options: BufferEncodingOption): Promise; + function __promisify__(path: PathLike, options: BufferEncodingOption): Promise; /** * Asynchronous readlink(2) - read value of a symbolic link. * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. */ - function __promisify__(path: PathLike, options?: EncodingOption): Promise; + function __promisify__(path: PathLike, options?: EncodingOption): Promise; } /** * Returns the symbolic link's string value. @@ -1425,13 +1614,13 @@ declare module "fs" { * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. */ - export function readlinkSync(path: PathLike, options: BufferEncodingOption): Buffer; + export function readlinkSync(path: PathLike, options: BufferEncodingOption): NonSharedBuffer; /** * Synchronous readlink(2) - read value of a symbolic link. * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. */ - export function readlinkSync(path: PathLike, options?: EncodingOption): string | Buffer; + export function readlinkSync(path: PathLike, options?: EncodingOption): string | NonSharedBuffer; /** * Asynchronously computes the canonical pathname by resolving `.`, `..`, and * symbolic links. @@ -1471,7 +1660,7 @@ declare module "fs" { export function realpath( path: PathLike, options: BufferEncodingOption, - callback: (err: NodeJS.ErrnoException | null, resolvedPath: Buffer) => void, + callback: (err: NodeJS.ErrnoException | null, resolvedPath: NonSharedBuffer) => void, ): void; /** * Asynchronous realpath(3) - return the canonicalized absolute pathname. @@ -1481,7 +1670,7 @@ declare module "fs" { export function realpath( path: PathLike, options: EncodingOption, - callback: (err: NodeJS.ErrnoException | null, resolvedPath: string | Buffer) => void, + callback: (err: NodeJS.ErrnoException | null, resolvedPath: string | NonSharedBuffer) => void, ): void; /** * Asynchronous realpath(3) - return the canonicalized absolute pathname. @@ -1503,13 +1692,13 @@ declare module "fs" { * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. */ - function __promisify__(path: PathLike, options: BufferEncodingOption): Promise; + function __promisify__(path: PathLike, options: BufferEncodingOption): Promise; /** * Asynchronous realpath(3) - return the canonicalized absolute pathname. * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. */ - function __promisify__(path: PathLike, options?: EncodingOption): Promise; + function __promisify__(path: PathLike, options?: EncodingOption): Promise; /** * Asynchronous [`realpath(3)`](http://man7.org/linux/man-pages/man3/realpath.3.html). * @@ -1535,12 +1724,12 @@ declare module "fs" { function native( path: PathLike, options: BufferEncodingOption, - callback: (err: NodeJS.ErrnoException | null, resolvedPath: Buffer) => void, + callback: (err: NodeJS.ErrnoException | null, resolvedPath: NonSharedBuffer) => void, ): void; function native( path: PathLike, options: EncodingOption, - callback: (err: NodeJS.ErrnoException | null, resolvedPath: string | Buffer) => void, + callback: (err: NodeJS.ErrnoException | null, resolvedPath: string | NonSharedBuffer) => void, ): void; function native( path: PathLike, @@ -1560,17 +1749,17 @@ declare module "fs" { * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. */ - export function realpathSync(path: PathLike, options: BufferEncodingOption): Buffer; + export function realpathSync(path: PathLike, options: BufferEncodingOption): NonSharedBuffer; /** * Synchronous realpath(3) - return the canonicalized absolute pathname. * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. */ - export function realpathSync(path: PathLike, options?: EncodingOption): string | Buffer; + export function realpathSync(path: PathLike, options?: EncodingOption): string | NonSharedBuffer; export namespace realpathSync { function native(path: PathLike, options?: EncodingOption): string; - function native(path: PathLike, options: BufferEncodingOption): Buffer; - function native(path: PathLike, options?: EncodingOption): string | Buffer; + function native(path: PathLike, options: BufferEncodingOption): NonSharedBuffer; + function native(path: PathLike, options?: EncodingOption): string | NonSharedBuffer; } /** * Asynchronously removes a file or symbolic link. No arguments other than a @@ -1898,7 +2087,7 @@ declare module "fs" { * The `fs.mkdtemp()` method will append the six randomly selected characters * directly to the `prefix` string. For instance, given a directory `/tmp`, if the * intention is to create a temporary directory _within_`/tmp`, the `prefix`must end with a trailing platform-specific path separator - * (`require('node:path').sep`). + * (`import { sep } from 'node:path'`). * * ```js * import { tmpdir } from 'node:os'; @@ -1940,12 +2129,8 @@ declare module "fs" { */ export function mkdtemp( prefix: string, - options: - | "buffer" - | { - encoding: "buffer"; - }, - callback: (err: NodeJS.ErrnoException | null, folder: Buffer) => void, + options: BufferEncodingOption, + callback: (err: NodeJS.ErrnoException | null, folder: NonSharedBuffer) => void, ): void; /** * Asynchronously creates a unique temporary directory. @@ -1955,7 +2140,7 @@ declare module "fs" { export function mkdtemp( prefix: string, options: EncodingOption, - callback: (err: NodeJS.ErrnoException | null, folder: string | Buffer) => void, + callback: (err: NodeJS.ErrnoException | null, folder: string | NonSharedBuffer) => void, ): void; /** * Asynchronously creates a unique temporary directory. @@ -1977,13 +2162,13 @@ declare module "fs" { * Generates six random characters to be appended behind a required prefix to create a unique temporary directory. * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. */ - function __promisify__(prefix: string, options: BufferEncodingOption): Promise; + function __promisify__(prefix: string, options: BufferEncodingOption): Promise; /** * Asynchronously creates a unique temporary directory. * Generates six random characters to be appended behind a required prefix to create a unique temporary directory. * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. */ - function __promisify__(prefix: string, options?: EncodingOption): Promise; + function __promisify__(prefix: string, options?: EncodingOption): Promise; } /** * Returns the created directory path. @@ -2001,13 +2186,46 @@ declare module "fs" { * Generates six random characters to be appended behind a required prefix to create a unique temporary directory. * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. */ - export function mkdtempSync(prefix: string, options: BufferEncodingOption): Buffer; + export function mkdtempSync(prefix: string, options: BufferEncodingOption): NonSharedBuffer; /** * Synchronously creates a unique temporary directory. * Generates six random characters to be appended behind a required prefix to create a unique temporary directory. * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. */ - export function mkdtempSync(prefix: string, options?: EncodingOption): string | Buffer; + export function mkdtempSync(prefix: string, options?: EncodingOption): string | NonSharedBuffer; + export interface DisposableTempDir extends AsyncDisposable { + /** + * The path of the created directory. + */ + path: string; + /** + * A function which removes the created directory. + */ + remove(): Promise; + /** + * The same as `remove`. + */ + [Symbol.asyncDispose](): Promise; + } + /** + * Returns a disposable object whose `path` property holds the created directory + * path. When the object is disposed, the directory and its contents will be + * removed if it still exists. If the directory cannot be deleted, disposal will + * throw an error. The object has a `remove()` method which will perform the same + * task. + * + * + * + * For detailed information, see the documentation of `fs.mkdtemp()`. + * + * There is no callback-based version of this API because it is designed for use + * with the `using` syntax. + * + * The optional `options` argument can be a string specifying an encoding, or an + * object with an `encoding` property specifying the character encoding to use. + * @since v24.4.0 + */ + export function mkdtempDisposableSync(prefix: string, options?: EncodingOption): DisposableTempDir; /** * Reads the contents of a directory. The callback gets two arguments `(err, files)` where `files` is an array of the names of the files in the directory excluding `'.'` and `'..'`. * @@ -2048,7 +2266,7 @@ declare module "fs" { recursive?: boolean | undefined; } | "buffer", - callback: (err: NodeJS.ErrnoException | null, files: Buffer[]) => void, + callback: (err: NodeJS.ErrnoException | null, files: NonSharedBuffer[]) => void, ): void; /** * Asynchronous readdir(3) - read a directory. @@ -2065,7 +2283,7 @@ declare module "fs" { | BufferEncoding | undefined | null, - callback: (err: NodeJS.ErrnoException | null, files: string[] | Buffer[]) => void, + callback: (err: NodeJS.ErrnoException | null, files: string[] | NonSharedBuffer[]) => void, ): void; /** * Asynchronous readdir(3) - read a directory. @@ -2088,6 +2306,20 @@ declare module "fs" { }, callback: (err: NodeJS.ErrnoException | null, files: Dirent[]) => void, ): void; + /** + * Asynchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Must include `withFileTypes: true` and `encoding: 'buffer'`. + */ + export function readdir( + path: PathLike, + options: { + encoding: "buffer"; + withFileTypes: true; + recursive?: boolean | undefined; + }, + callback: (err: NodeJS.ErrnoException | null, files: Dirent[]) => void, + ): void; export namespace readdir { /** * Asynchronous readdir(3) - read a directory. @@ -2119,7 +2351,7 @@ declare module "fs" { withFileTypes?: false | undefined; recursive?: boolean | undefined; }, - ): Promise; + ): Promise; /** * Asynchronous readdir(3) - read a directory. * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. @@ -2134,7 +2366,7 @@ declare module "fs" { }) | BufferEncoding | null, - ): Promise; + ): Promise; /** * Asynchronous readdir(3) - read a directory. * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. @@ -2147,6 +2379,19 @@ declare module "fs" { recursive?: boolean | undefined; }, ): Promise; + /** + * Asynchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Must include `withFileTypes: true` and `encoding: 'buffer'`. + */ + function __promisify__( + path: PathLike, + options: { + encoding: "buffer"; + withFileTypes: true; + recursive?: boolean | undefined; + }, + ): Promise[]>; } /** * Reads the contents of the directory. @@ -2186,7 +2431,7 @@ declare module "fs" { recursive?: boolean | undefined; } | "buffer", - ): Buffer[]; + ): NonSharedBuffer[]; /** * Synchronous readdir(3) - read a directory. * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. @@ -2201,7 +2446,7 @@ declare module "fs" { }) | BufferEncoding | null, - ): string[] | Buffer[]; + ): string[] | NonSharedBuffer[]; /** * Synchronous readdir(3) - read a directory. * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. @@ -2214,6 +2459,19 @@ declare module "fs" { recursive?: boolean | undefined; }, ): Dirent[]; + /** + * Synchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Must include `withFileTypes: true` and `encoding: 'buffer'`. + */ + export function readdirSync( + path: PathLike, + options: { + encoding: "buffer"; + withFileTypes: true; + recursive?: boolean | undefined; + }, + ): Dirent
Liga: {{ parsedData.leagueName }}
Verband: {{ parsedData.association }}
Tabelle: Platz {{ parsedData.tableRank }}