This commit is contained in:
soufiane 2025-11-17 23:47:54 +01:00
parent 67316ef0b1
commit 25c7a0b304
6787 changed files with 550392 additions and 109 deletions

13
.env
View File

@ -1,14 +1,15 @@
DB_HOST=the-tip-top-db
DB_HOST=51.75.24.29
DB_PORT=5433
DB_USER=postgres
DB_PASS=postgres
DB_NAME=thetiptop
DB_NAME=thetiptop_dev
PORT=4000
JWT_SECRET=thetiptopsecret
GOOGLE_CLIENT_ID=546665126481-nmfcsbrjm6an7tbnv2jbspihgtu72ifn.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=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
FACEBOOK_APP_ID=ton_app_id_facebook
FACEBOOK_APP_SECRET=ton_secret_facebook
GOOGLE_CLIENT_ID=546665126481-itnlvt22hjn6t0bbgua0aj55h6dpplsk.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=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
FACEBOOK_APP_ID=836681122652445
FACEBOOK_APP_SECRET=e6889f4339d140c218f1df177149893f
JWT_SECRET=thetiptopsecret
SESSION_SECRET=thetiptopsessionsecret

22
.env.dev Normal file
View File

@ -0,0 +1,22 @@
# Environnement DEV
NODE_ENV=development
DB_HOST=51.75.24.29
DB_PORT=5433
DB_USER=postgres
DB_PASS=postgres
DB_NAME=thetiptop_dev
PORT=4000
# URLs Frontend/Backend
FRONTEND_URL=https://dev.dsp5-archi-o24a-15m-g3.fr
BACKEND_URL=https://api.dev.dsp5-archi-o24a-15m-g3.fr
# JWT
JWT_SECRET=thetiptopsecret_dev
SESSION_SECRET=thetiptopsessionsecret_dev
# OAuth (à configurer avec les URLs de dev)
GOOGLE_CLIENT_ID=546665126481-itnlvt22hjn6t0bbgua0aj55h6dpplsk.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=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
FACEBOOK_APP_ID=836681122652445
FACEBOOK_APP_SECRET=e6889f4339d140c218f1df177149893f

22
.env.preprod Normal file
View File

@ -0,0 +1,22 @@
# Environnement PREPROD
NODE_ENV=preproduction
DB_HOST=51.75.24.29
DB_PORT=5434
DB_USER=postgres
DB_PASS=postgres
DB_NAME=thetiptop_preprod
PORT=4000
# URLs Frontend/Backend
FRONTEND_URL=https://preprod.dsp5-archi-o24a-15m-g3.fr
BACKEND_URL=https://api.preprod.dsp5-archi-o24a-15m-g3.fr
# JWT (Secrets générés automatiquement)
JWT_SECRET=koN619HNfIgBKrCRl6o1feaVg30GPHQR+4DvbCoxmlA=
SESSION_SECRET=DXgw+RHWLjW40G33fe5NqPnzwMkKf7bVxx3wZROkypM=
# OAuth
GOOGLE_CLIENT_ID=546665126481-itnlvt22hjn6t0bbgua0aj55h6dpplsk.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=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
FACEBOOK_APP_ID=836681122652445
FACEBOOK_APP_SECRET=e6889f4339d140c218f1df177149893f

22
.env.production Normal file
View File

@ -0,0 +1,22 @@
# Environnement PRODUCTION
NODE_ENV=production
DB_HOST=51.75.24.29
DB_PORT=5432
DB_USER=postgres
DB_PASS=postgres
DB_NAME=thetiptop
PORT=4000
# URLs Frontend/Backend
FRONTEND_URL=https://dsp5-archi-o24a-15m-g3.fr
BACKEND_URL=https://api.dsp5-archi-o24a-15m-g3.fr
# JWT (Secrets générés automatiquement)
JWT_SECRET=v0vIxcahaOdJMzqoKjRpCGkRFyVTVDJyk7s2F1LIXu0=
SESSION_SECRET=BzTTnx+GxsBpdVMcBKH5Vo6gH7h+/7tlZ67nppNduoY=
# OAuth
GOOGLE_CLIENT_ID=546665126481-itnlvt22hjn6t0bbgua0aj55h6dpplsk.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=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
FACEBOOK_APP_ID=836681122652445
FACEBOOK_APP_SECRET=e6889f4339d140c218f1df177149893f

1100
API-DOCUMENTATION.md Normal file

File diff suppressed because it is too large Load Diff

197
DEPLOYMENT-WORKFLOW.md Normal file
View File

@ -0,0 +1,197 @@
# 🚀 Workflow de Déploiement - Thé Tip Top
## 📊 Vue d'ensemble des environnements
| Environnement | Branche | Base de données | Port DB | URLs |
|---------------|---------|-----------------|---------|------|
| **DEV** | `dev` | `thetiptop_dev` | 5433 | https://dev.dsp5-archi-o24a-15m-g3.fr<br>https://api.dev.dsp5-archi-o24a-15m-g3.fr |
| **PREPROD** | `preprod` | `thetiptop_preprod` | 5434 | https://preprod.dsp5-archi-o24a-15m-g3.fr<br>https://api.preprod.dsp5-archi-o24a-15m-g3.fr |
| **PROD** | `main` | `thetiptop` | 5432 | https://dsp5-archi-o24a-15m-g3.fr<br>https://api.dsp5-archi-o24a-15m-g3.fr |
---
## 🔄 Workflow Git
```
dev → preprod → main
↓ ↓ ↓
DEV PREPROD PROD
```
---
## 📝 Procédure de déploiement
### 1⃣ **Développement sur DEV**
```bash
# Vous êtes sur la branche dev
git checkout dev
# Faire vos modifications...
# Commit et push vers dev
git add .
git commit -m "feat: description de la fonctionnalité"
git push origin dev
```
**Déploiement DEV :**
```bash
# Sur le serveur DEV
cd /path/to/backend
git pull origin dev
cp .env.dev .env
npm install
npm run dev
```
---
### 2⃣ **Déploiement vers PREPROD**
Après avoir testé sur DEV et validé les fonctionnalités :
```bash
# Merger dev vers preprod
git checkout preprod
git pull origin preprod
git merge dev
git push origin preprod
```
**Déploiement PREPROD :**
```bash
# Sur le serveur PREPROD
cd /path/to/backend
git pull origin preprod
cp .env.preprod .env
npm install
npm run dev
```
**⚠️ Tests à effectuer en PREPROD :**
- [ ] Toutes les fonctionnalités principales
- [ ] Authentification (Google, Facebook)
- [ ] Jeu et attribution des lots
- [ ] Interface admin
- [ ] Tirage au sort
- [ ] Performance et sécurité
---
### 3⃣ **Déploiement en PRODUCTION**
Après validation complète en PREPROD :
```bash
# Merger preprod vers main
git checkout main
git pull origin main
git merge preprod
git push origin main
```
**Déploiement PRODUCTION :**
```bash
# Sur le serveur PRODUCTION
cd /path/to/backend
git pull origin main
cp .env.production .env
# ⚠️ IMPORTANT : Vérifier les secrets en production
nano .env # Vérifier JWT_SECRET, SESSION_SECRET, etc.
npm install
npm run build # Si nécessaire
npm start
```
---
## 🗄️ Gestion des bases de données
### Migration de données DEV → PREPROD
```bash
# Dump de la base DEV
pg_dump -h 51.75.24.29 -p 5433 -U postgres -d thetiptop_dev > dev_dump.sql
# Restaurer en PREPROD
psql -h 51.75.24.29 -p 5434 -U postgres -d thetiptop_preprod < dev_dump.sql
```
### Migration de données PREPROD → PROD
```bash
# Dump de la base PREPROD
pg_dump -h 51.75.24.29 -p 5434 -U postgres -d thetiptop_preprod > preprod_dump.sql
# ⚠️ BACKUP PROD avant restauration !
pg_dump -h 51.75.24.29 -p 5432 -U postgres -d thetiptop > prod_backup_$(date +%Y%m%d).sql
# Restaurer en PROD
psql -h 51.75.24.29 -p 5432 -U postgres -d thetiptop < preprod_dump.sql
```
---
## 🔐 Configuration des secrets
### Secrets à changer ABSOLUMENT en PRODUCTION :
- `JWT_SECRET` - Générer avec : `openssl rand -base64 32`
- `SESSION_SECRET` - Générer avec : `openssl rand -base64 32`
- `NEXTAUTH_SECRET` - Générer avec : `openssl rand -base64 32`
### OAuth en production :
1. **Google OAuth** : Créer un nouveau projet sur Google Cloud Console avec les URLs de prod
2. **Facebook OAuth** : Créer une nouvelle app Facebook avec les URLs de prod
---
## ✅ Checklist avant déploiement PRODUCTION
- [ ] Tous les tests passent en PREPROD
- [ ] Les secrets ont été changés (JWT, SESSION)
- [ ] OAuth configuré avec les URLs de production
- [ ] Backup de la base de données PROD effectué
- [ ] Variables d'environnement vérifiées
- [ ] CORS configuré avec les domaines de production
- [ ] Logs configurés pour la production
- [ ] Plan de rollback préparé
---
## 🚨 Rollback en cas de problème
### Si problème en PRODUCTION :
```bash
# 1. Revenir à la version précédente
git checkout main
git reset --hard <commit-précédent>
git push origin main --force
# 2. Restaurer le backup de la base de données
psql -h 51.75.24.29 -p 5432 -U postgres -d thetiptop < prod_backup_YYYYMMDD.sql
# 3. Redémarrer l'application
npm start
```
---
## 📞 Support
En cas de problème, vérifier :
1. Les logs du serveur
2. Les logs de la base de données
3. Les variables d'environnement
4. La configuration CORS
5. Les certificats SSL
---
**Dernière mise à jour** : $(date +%Y-%m-%d)

159
README.md Normal file
View File

@ -0,0 +1,159 @@
# The Tip Top Backend API
API backend pour le jeu-concours The Tip Top.
## Configuration
### Variables d'environnement
Le fichier `.env` contient la configuration de la base de données et de l'application :
```env
DB_HOST=51.75.24.29
DB_PORT=5433
DB_USER=postgres
DB_PASS=postgres
DB_NAME=thetiptop_dev
PORT=4000
JWT_SECRET=thetiptopsecret
SESSION_SECRET=thetiptopsessionsecret
```
**Note** : La base de données PostgreSQL est hébergée sur le serveur distant `51.75.24.29:5433`.
## Installation
```bash
# Installer les dépendances
npm install
# Créer le schéma de la base de données
psql -U postgres -d thetiptop_dev -p 5433 -f database/schema.sql
# Insérer les données de test
npm run db:seed
```
## Démarrage
### Démarrage normal
```bash
npm start
```
### Démarrage en mode développement (avec nodemon)
```bash
npm run dev
```
### Arrêter le serveur
**Sur Windows :**
1. Ouvrez le Gestionnaire des tâches (Ctrl + Shift + Esc)
2. Cherchez les processus "Node.js"
3. Terminez-les tous
**Ou via PowerShell :**
```powershell
Get-Process node | Stop-Process -Force
```
## Structure du projet
```
the-tip-top-backend/
├── database/
│ ├── schema.sql # Schéma de la base de données
│ ├── seed.js # Script de seed
│ └── README.md # Documentation DB
├── src/
│ ├── config/
│ │ └── env.js # Configuration environnement
│ ├── controllers/ # Contrôleurs (logique métier)
│ ├── middleware/ # Middlewares (auth, validation, erreurs)
│ ├── routes/ # Définition des routes
│ ├── services/ # Services (email, etc.)
│ ├── utils/ # Utilitaires
│ └── validations/ # Schémas de validation Zod
├── db.js # Configuration PostgreSQL
├── index.js # Point d'entrée de l'application
└── .env # Variables d'environnement
```
## Routes API
### Authentification (`/api/auth`)
- `POST /register` - Inscription
- `POST /login` - Connexion
- `GET /verify-email/:token` - Vérification email
- `POST /forgot-password` - Demande de réinitialisation
- `POST /reset-password` - Réinitialisation du mot de passe
### Utilisateur (`/api/users`)
- `GET /profile` - Récupérer le profil
- `PUT /profile` - Mettre à jour le profil
- `POST /change-password` - Changer le mot de passe
### Jeu (`/api/game`)
- `POST /play` - Jouer et obtenir un ticket
- `GET /my-tickets` - Mes tickets
- `GET /ticket/:code` - Détails d'un ticket
### Employé (`/api/employee`)
- `POST /validate-ticket` - Valider un ticket
- `GET /pending-tickets` - Tickets en attente
### Admin (`/api/admin`)
- `GET /statistics` - Statistiques globales
- `GET /prizes` - Liste des prix
- `POST /prizes` - Créer un prix
- `PUT /prizes/:id` - Modifier un prix
- `DELETE /prizes/:id` - Supprimer un prix
- `GET /users` - Liste des utilisateurs
- `POST /employees` - Créer un employé
- `PUT /users/:id` - Modifier un utilisateur
- `DELETE /users/:id` - Supprimer un utilisateur
- `GET /tickets` - Liste des tickets
## Comptes de test
Après avoir exécuté le seed :
| Email | Mot de passe | Rôle |
|-------|-------------|------|
| admin@thetiptop.com | Admin123! | ADMIN |
| employee1@thetiptop.com | Employee123! | EMPLOYEE |
| employee2@thetiptop.com | Employee123! | EMPLOYEE |
| client1@example.com | Client123! | CLIENT |
| client2-5@example.com | Client123! | CLIENT |
## Tests
```bash
# Tests unitaires
npm test
# Tests d'intégration
npm run test:integration
```
## Endpoints de monitoring
- `GET /` - Health check
- `GET /db-check` - Vérification connexion DB
- `GET /metrics` - Métriques Prometheus
## Technologies
- **Express** - Framework web
- **PostgreSQL** - Base de données
- **JWT** - Authentification
- **Bcrypt** - Hashage de mots de passe
- **Zod** - Validation des données
- **Nodemailer** - Envoi d'emails
- **Helmet** - Sécurité HTTP
- **CORS** - Gestion des origines
- **Morgan** - Logs HTTP
- **Prometheus** - Métriques

44
RESTART-ALL.ps1 Normal file
View File

@ -0,0 +1,44 @@
Write-Host "========================================" -ForegroundColor Cyan
Write-Host " RESTART BACKEND AND FRONTEND" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "Step 1: Stopping all Node.js processes..." -ForegroundColor Yellow
$nodeProcesses = Get-Process node -ErrorAction SilentlyContinue
if ($nodeProcesses) {
$nodeProcesses | Stop-Process -Force
Write-Host "[OK] Stopped $($nodeProcesses.Count) Node.js process(es)" -ForegroundColor Green
} else {
Write-Host "[INFO] No Node.js processes running" -ForegroundColor Gray
}
Write-Host ""
Write-Host "Waiting 3 seconds for ports to be released..." -ForegroundColor Yellow
Start-Sleep -Seconds 3
Write-Host ""
Write-Host "Step 2: Starting Backend..." -ForegroundColor Yellow
$backendPath = "C:\Users\LENOVO\Back\the-tip-top-backend"
Start-Process powershell -ArgumentList "-NoExit", "-Command", "cd '$backendPath'; npm start" -WindowStyle Normal
Write-Host "[OK] Backend starting..." -ForegroundColor Green
Write-Host ""
Write-Host "Waiting 5 seconds for backend to initialize..." -ForegroundColor Yellow
Start-Sleep -Seconds 5
Write-Host ""
Write-Host "Step 3: Starting Frontend..." -ForegroundColor Yellow
$frontendPath = "C:\Users\LENOVO\front\the-tip-top-frontend"
Start-Process powershell -ArgumentList "-NoExit", "-Command", "cd '$frontendPath'; npm run dev" -WindowStyle Normal
Write-Host "[OK] Frontend starting..." -ForegroundColor Green
Write-Host ""
Write-Host "========================================" -ForegroundColor Cyan
Write-Host " RESTART COMPLETE" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "Backend: http://localhost:4000" -ForegroundColor White
Write-Host "Frontend: http://localhost:3004" -ForegroundColor White
Write-Host ""
Write-Host "Press any key to close this window..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")

39
RESTART-FORCE.bat Normal file
View File

@ -0,0 +1,39 @@
@echo off
cls
echo.
echo ========================================
echo ARRET FORCE DE TOUS LES NODE.JS
echo ========================================
echo.
echo Etape 1: Arret de TOUS les processus Node...
echo.
REM Tuer tous les processus Node
taskkill /F /IM node.exe /T 2>nul
if %errorlevel% equ 0 (
echo [OK] Processus Node arretes
) else (
echo [INFO] Aucun processus Node trouve
)
echo.
echo Attente de 5 secondes...
timeout /t 5 /nobreak >nul
echo.
echo ========================================
echo DEMARRAGE DU BACKEND
echo ========================================
echo.
echo Dossier: C:\Users\LENOVO\Back\the-tip-top-backend
echo Commande: npm start
echo.
echo Le backend va demarrer dans 3 secondes...
timeout /t 3 /nobreak >nul
cd /d "C:\Users\LENOVO\Back\the-tip-top-backend"
echo.
echo *** BACKEND EN COURS DE DEMARRAGE ***
echo.
npm start

14
backend.log Normal file
View File

@ -0,0 +1,14 @@
> backend@1.0.0 start
> node index.js
[dotenv@17.2.3] injecting env (12) from .env -- tip: ⚙️ specify custom .env file path with { path: '/custom/path/.env' }
🧩 DB Config → {
host: '51.75.24.29',
port: '5433',
user: 'postgres',
pass: '***',
database: 'thetiptop_dev'
}
[dotenv@17.2.3] injecting env (0) from .env -- tip: ⚙️ suppress all logs with { quiet: true }
🚀 Backend lancé sur 0.0.0.0:4000 ✅

10
create-test-users.sql Normal file
View File

@ -0,0 +1,10 @@
-- Script pour créer des utilisateurs de test avec différents rôles
-- À exécuter dans PostgreSQL
-- Promouvoir les utilisateurs existants
UPDATE users SET role = 'ADMIN' WHERE email = 'admin@test.com';
UPDATE users SET role = 'EMPLOYEE' WHERE email = 'employee@test.com';
-- Vérifier les utilisateurs
SELECT email, role, is_verified FROM users
WHERE email IN ('test-client@test.com', 'employee@test.com', 'admin@test.com');

113
database/README.md Normal file
View File

@ -0,0 +1,113 @@
# Database Setup
Ce dossier contient le schéma SQL et le script de seed pour la base de données PostgreSQL.
## Structure
- `schema.sql` - Schéma complet de la base de données (tables, index, triggers, vues)
- `seed.js` - Script pour insérer des données de test
## Installation
### 1. Créer le schéma
Exécutez le fichier SQL pour créer toutes les tables et insérer les données initiales (prix, configuration du jeu) :
```bash
psql -U postgres -d thetiptop -f database/schema.sql
```
Ou utilisez le script npm :
```bash
npm run db:schema
```
### 2. Insérer les données de test
Exécutez le script de seed pour créer des utilisateurs et tickets de test :
```bash
npm run db:seed
```
## Données de test créées
Le script de seed crée :
### Utilisateurs
| Email | Mot de passe | Rôle |
|-------|-------------|------|
| admin@thetiptop.com | Admin123! | ADMIN |
| employee1@thetiptop.com | Employee123! | EMPLOYEE |
| employee2@thetiptop.com | Employee123! | EMPLOYEE |
| client1@example.com | Client123! | CLIENT |
| client2@example.com | Client123! | CLIENT |
| client3@example.com | Client123! | CLIENT |
| client4@example.com | Client123! | CLIENT |
| client5@example.com | Client123! | CLIENT |
### Tickets
- Environ 15-25 tickets répartis entre les clients
- 80% en statut PENDING
- 10% en statut CLAIMED
- 10% en statut REJECTED
- Prix distribués aléatoirement
## Schéma de la base de données
### Tables principales
#### users
Stocke tous les utilisateurs (clients, employés, admins)
- Authentification par email/password
- Vérification par email
- Récupération de mot de passe
#### prizes
Les différents prix disponibles dans le jeu-concours
- 5 types de prix (INFUSEUR, THE_SIGNATURE, COFFRET_DECOUVERTE, COFFRET_PRESTIGE, THE_GRATUIT)
- Stock et probabilités configurables
- Gestion du statut actif/inactif
#### tickets
Les tickets de jeu générés pour chaque participation
- Code unique
- Statuts: PENDING, CLAIMED, REJECTED
- Lié à un utilisateur et un prix
- Traçabilité de la validation
#### game_settings
Configuration générale du jeu-concours
- Dates de début et fin
- Nombre total de tickets
- Statut actif/inactif
### Vues utiles
#### prize_statistics
Statistiques agrégées par prix (stock initial, utilisé, restant, etc.)
#### pending_tickets
Liste des tickets en attente de validation avec toutes les informations nécessaires
## Réinitialisation
Pour réinitialiser complètement la base de données :
```bash
# 1. Supprimer et recréer le schéma
npm run db:schema
# 2. Insérer les données de test
npm run db:seed
```
## Notes
- Le schéma utilise des UUID pour tous les IDs
- Les triggers mettent automatiquement à jour les champs `updated_at`
- Les index sont créés sur les colonnes fréquemment utilisées pour optimiser les performances
- Les contraintes CASCADE assurent l'intégrité référentielle

View File

@ -0,0 +1,49 @@
# Migrations de Base de Données
Ce dossier contient les migrations pour la base de données The Tip Top.
## Migration: Ajout des champs démographiques
### Fichier: `add-demographics-fields.sql`
Cette migration ajoute les champs nécessaires pour les statistiques démographiques:
- `gender` (ENUM: MALE, FEMALE, OTHER, NOT_SPECIFIED)
- `date_of_birth` (DATE)
### Comment exécuter la migration
#### Option 1: Via psql
```bash
psql -h 51.75.24.29 -U postgres -d thetiptop_dev -p 5433 -f database/migrations/add-demographics-fields.sql
```
#### Option 2: Via un client SQL (DBeaver, pgAdmin, etc.)
1. Connectez-vous à votre base de données
2. Ouvrez le fichier `add-demographics-fields.sql`
3. Exécutez le script
### Vérification
Pour vérifier que la migration a été appliquée correctement:
```sql
-- Vérifier les nouvelles colonnes
SELECT column_name, data_type
FROM information_schema.columns
WHERE table_name = 'users'
AND column_name IN ('gender', 'date_of_birth');
-- Vérifier le type ENUM gender_type
SELECT typname, enumlabel
FROM pg_type
JOIN pg_enum ON pg_type.oid = pg_enum.enumtypid
WHERE typname = 'gender_type';
```
## Notes importantes
- Cette migration est idempotente (peut être exécutée plusieurs fois sans erreur)
- Les valeurs par défaut sont définies pour ne pas affecter les données existantes
- Les index sont créés automatiquement pour améliorer les performances des requêtes de statistiques

View File

@ -0,0 +1,38 @@
-- ============================================
-- MIGRATION: Ajout des champs démographiques
-- ============================================
-- Créer le type ENUM pour le genre
DO $$ BEGIN
CREATE TYPE gender_type AS ENUM ('MALE', 'FEMALE', 'OTHER', 'NOT_SPECIFIED');
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
-- Ajouter les colonnes gender et date_of_birth à la table users si elles n'existent pas
DO $$
BEGIN
-- Ajouter la colonne gender si elle n'existe pas
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'users' AND column_name = 'gender'
) THEN
ALTER TABLE users ADD COLUMN gender gender_type DEFAULT 'NOT_SPECIFIED';
END IF;
-- Ajouter la colonne date_of_birth si elle n'existe pas
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'users' AND column_name = 'date_of_birth'
) THEN
ALTER TABLE users ADD COLUMN date_of_birth DATE;
END IF;
END $$;
-- Créer un index sur gender pour améliorer les performances des requêtes de statistiques
CREATE INDEX IF NOT EXISTS idx_users_gender ON users(gender);
CREATE INDEX IF NOT EXISTS idx_users_date_of_birth ON users(date_of_birth);
-- Commentaires
COMMENT ON COLUMN users.gender IS 'Genre de l''utilisateur: MALE, FEMALE, OTHER, NOT_SPECIFIED';
COMMENT ON COLUMN users.date_of_birth IS 'Date de naissance de l''utilisateur pour les statistiques démographiques';

View File

@ -0,0 +1,73 @@
-- Migration: Système de campagnes email
-- Date: 2025-11-14
-- Description: Tables pour gérer les campagnes d'emailing
-- Table des campagnes email
CREATE TABLE IF NOT EXISTS email_campaigns (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255) NOT NULL,
subject VARCHAR(500) NOT NULL,
template_html TEXT NOT NULL,
template_text TEXT,
created_by UUID NOT NULL REFERENCES users(id),
status VARCHAR(50) DEFAULT 'DRAFT', -- DRAFT, SCHEDULED, SENT, CANCELLED
scheduled_at TIMESTAMP,
sent_at TIMESTAMP,
recipient_count INTEGER DEFAULT 0,
opened_count INTEGER DEFAULT 0,
clicked_count INTEGER DEFAULT 0,
criteria JSONB, -- Critères de ciblage
notes TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Table des destinataires (pour tracking individuel)
CREATE TABLE IF NOT EXISTS email_campaign_recipients (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
campaign_id UUID NOT NULL REFERENCES email_campaigns(id) ON DELETE CASCADE,
user_id UUID NOT NULL REFERENCES users(id),
email VARCHAR(255) NOT NULL,
status VARCHAR(50) DEFAULT 'PENDING', -- PENDING, SENT, FAILED, BOUNCED
sent_at TIMESTAMP,
opened_at TIMESTAMP,
clicked_at TIMESTAMP,
unsubscribed_at TIMESTAMP,
error_message TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Table des templates prédéfinis
CREATE TABLE IF NOT EXISTS email_templates (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255) NOT NULL,
description TEXT,
subject VARCHAR(500),
html_content TEXT NOT NULL,
text_content TEXT,
category VARCHAR(100), -- welcome, promotion, notification, etc.
is_active BOOLEAN DEFAULT TRUE,
created_by UUID REFERENCES users(id),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Index pour performance
CREATE INDEX IF NOT EXISTS idx_email_campaigns_status ON email_campaigns(status);
CREATE INDEX IF NOT EXISTS idx_email_campaigns_created_by ON email_campaigns(created_by);
CREATE INDEX IF NOT EXISTS idx_email_campaigns_scheduled_at ON email_campaigns(scheduled_at);
CREATE INDEX IF NOT EXISTS idx_email_campaign_recipients_campaign ON email_campaign_recipients(campaign_id);
CREATE INDEX IF NOT EXISTS idx_email_campaign_recipients_user ON email_campaign_recipients(user_id);
CREATE INDEX IF NOT EXISTS idx_email_campaign_recipients_status ON email_campaign_recipients(status);
CREATE INDEX IF NOT EXISTS idx_email_templates_category ON email_templates(category);
CREATE INDEX IF NOT EXISTS idx_email_templates_is_active ON email_templates(is_active);
-- Commentaires
COMMENT ON TABLE email_campaigns IS 'Campagnes email marketing';
COMMENT ON TABLE email_campaign_recipients IS 'Destinataires individuels avec tracking';
COMMENT ON TABLE email_templates IS 'Templates email reutilisables';
COMMENT ON COLUMN email_campaigns.criteria IS 'Criteres JSON de ciblage des destinataires';
COMMENT ON COLUMN email_campaigns.status IS 'DRAFT=Brouillon, SCHEDULED=Planifie, SENT=Envoye, CANCELLED=Annule';

View File

@ -0,0 +1,49 @@
-- Migration: Ajout de la table pour les tirages au sort du gros lot
-- Date: 2025-11-13
-- Table pour stocker les tirages au sort
CREATE TABLE IF NOT EXISTS grand_prize_draws (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
-- Informations du tirage
draw_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
conducted_by UUID NOT NULL REFERENCES users(id), -- Admin qui a lancé le tirage
-- Gagnant
winner_id UUID NOT NULL REFERENCES users(id),
winner_email VARCHAR(255) NOT NULL,
winner_name VARCHAR(255) NOT NULL,
-- Détails du lot
prize_name VARCHAR(255) NOT NULL,
prize_value VARCHAR(100),
-- Participants
total_participants INTEGER NOT NULL,
eligible_participants INTEGER NOT NULL,
-- Critères d'éligibilité utilisés
criteria JSONB, -- Stocke les critères du tirage
-- Statut
status VARCHAR(50) DEFAULT 'COMPLETED', -- COMPLETED, NOTIFIED, CLAIMED
notified_at TIMESTAMP,
claimed_at TIMESTAMP,
-- Metadata
notes TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT unique_grand_prize_draw UNIQUE (draw_date)
);
-- Index pour les recherches
CREATE INDEX IF NOT EXISTS idx_grand_prize_draws_winner ON grand_prize_draws(winner_id);
CREATE INDEX IF NOT EXISTS idx_grand_prize_draws_date ON grand_prize_draws(draw_date);
CREATE INDEX IF NOT EXISTS idx_grand_prize_draws_status ON grand_prize_draws(status);
-- Commentaires
COMMENT ON TABLE grand_prize_draws IS 'Stocke les tirages au sort du gros lot final';
COMMENT ON COLUMN grand_prize_draws.conducted_by IS 'Admin qui a effectué le tirage';
COMMENT ON COLUMN grand_prize_draws.criteria IS 'Critères d''éligibilité en JSON (ex: {minTickets: 1, verified: true})';
COMMENT ON COLUMN grand_prize_draws.status IS 'COMPLETED: tirage effectué, NOTIFIED: gagnant notifié, CLAIMED: lot récupéré';

View File

@ -0,0 +1,31 @@
-- Migration: Ajouter le type GRAND_PRIZE pour le gros lot du tirage final
-- Date: 2025-11-14
-- Ajouter le type GRAND_PRIZE à l'enum prize_type
ALTER TYPE prize_type ADD VALUE IF NOT EXISTS 'GRAND_PRIZE';
-- Créer le gros lot "An de thé" (360€)
INSERT INTO prizes (
type,
name,
description,
value,
stock,
probability,
is_active
) VALUES (
'GRAND_PRIZE',
'An de thé',
'Gros lot du tirage final - Un an de thé d''exception',
'360.00',
1,
0,
TRUE
)
ON CONFLICT (name) DO UPDATE SET
type = 'GRAND_PRIZE',
description = 'Gros lot du tirage final - Un an de thé d''exception',
value = '360.00',
stock = 1,
probability = 0,
is_active = TRUE;

View File

@ -0,0 +1,26 @@
-- Migration: Ajout du tracking de remise physique des lots
-- Date: 2025-11-14
-- Description: Ajoute les colonnes pour suivre la remise physique des lots
-- Ajouter la colonne delivered_at pour marquer la date de remise physique
ALTER TABLE tickets
ADD COLUMN IF NOT EXISTS delivered_at TIMESTAMP DEFAULT NULL;
-- Ajouter la colonne delivered_by pour tracer qui a remis le lot
ALTER TABLE tickets
ADD COLUMN IF NOT EXISTS delivered_by UUID DEFAULT NULL REFERENCES users(id);
-- Ajouter la colonne delivery_notes pour des notes sur la remise
ALTER TABLE tickets
ADD COLUMN IF NOT EXISTS delivery_notes TEXT DEFAULT NULL;
-- Créer un index sur delivered_at pour les requêtes de suivi
CREATE INDEX IF NOT EXISTS idx_tickets_delivered_at ON tickets(delivered_at);
-- Créer un index sur delivered_by
CREATE INDEX IF NOT EXISTS idx_tickets_delivered_by ON tickets(delivered_by);
-- Commentaires
COMMENT ON COLUMN tickets.delivered_at IS 'Date de remise physique du lot au gagnant';
COMMENT ON COLUMN tickets.delivered_by IS 'Employé/Admin qui a remis le lot';
COMMENT ON COLUMN tickets.delivery_notes IS 'Notes sur la remise (lieu, conditions, etc.)';

View File

@ -0,0 +1,27 @@
-- Migration pour corriger le schéma de la table tickets
-- Permet de créer des tickets non assignés (status=NULL, user_id=NULL)
-- 1. Modifier la colonne user_id pour accepter NULL
ALTER TABLE tickets
ALTER COLUMN user_id DROP NOT NULL;
-- 2. Modifier la colonne status pour ne pas avoir de valeur par défaut
ALTER TABLE tickets
ALTER COLUMN status DROP DEFAULT;
-- 3. Modifier la colonne played_at pour ne pas avoir de valeur par défaut
ALTER TABLE tickets
ALTER COLUMN played_at DROP DEFAULT;
-- 4. Mettre à jour les tickets existants qui ont été mal créés
-- (tickets avec PENDING mais sans user_id ou avec played_at par défaut)
UPDATE tickets
SET
status = NULL,
user_id = NULL,
played_at = NULL
WHERE user_id IS NULL OR played_at = created_at;
COMMENT ON COLUMN tickets.user_id IS 'NULL = ticket non joué, UUID = ticket joué par cet utilisateur';
COMMENT ON COLUMN tickets.status IS 'NULL = ticket non joué, PENDING/CLAIMED/REJECTED = statut après jeu';
COMMENT ON COLUMN tickets.played_at IS 'NULL = ticket non joué, TIMESTAMP = date de jeu';

View File

@ -0,0 +1,10 @@
-- Rendre le champ user_id nullable pour permettre les tickets non utilisés
-- Les 500,000 tickets du jeu-concours existent avant d'être attribués à un utilisateur
ALTER TABLE tickets
ALTER COLUMN user_id DROP NOT NULL;
-- Créer un index pour les tickets non utilisés pour optimiser les requêtes
CREATE INDEX IF NOT EXISTS idx_tickets_unused ON tickets(user_id) WHERE user_id IS NULL;
COMMENT ON COLUMN tickets.user_id IS 'ID de l''utilisateur - NULL pour les tickets non encore utilisés';

267
database/schema.sql Normal file
View File

@ -0,0 +1,267 @@
-- ============================================
-- SCHEMA SQL - THE TIP TOP DATABASE
-- ============================================
-- Drop tables if they exist
DROP TABLE IF EXISTS tickets CASCADE;
DROP TABLE IF EXISTS prizes CASCADE;
DROP TABLE IF EXISTS users CASCADE;
DROP TABLE IF EXISTS game_settings CASCADE;
-- Drop types if they exist
DROP TYPE IF EXISTS user_role CASCADE;
DROP TYPE IF EXISTS ticket_status CASCADE;
DROP TYPE IF EXISTS prize_type CASCADE;
-- ============================================
-- ENUMS
-- ============================================
CREATE TYPE user_role AS ENUM ('CLIENT', 'EMPLOYEE', 'ADMIN');
CREATE TYPE ticket_status AS ENUM ('PENDING', 'CLAIMED', 'REJECTED');
CREATE TYPE prize_type AS ENUM (
'INFUSEUR',
'THE_SIGNATURE',
'COFFRET_DECOUVERTE',
'COFFRET_PRESTIGE',
'THE_GRATUIT'
);
-- ============================================
-- TABLE: users
-- ============================================
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email VARCHAR(255) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL,
first_name VARCHAR(100) NOT NULL,
last_name VARCHAR(100) NOT NULL,
phone VARCHAR(20),
address TEXT,
city VARCHAR(100),
postal_code VARCHAR(10),
role user_role DEFAULT 'CLIENT',
is_verified BOOLEAN DEFAULT FALSE,
verification_token VARCHAR(255),
reset_token VARCHAR(255),
reset_token_expiry TIMESTAMP,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Index pour améliorer les performances
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_role ON users(role);
CREATE INDEX idx_users_verification_token ON users(verification_token);
CREATE INDEX idx_users_reset_token ON users(reset_token);
-- ============================================
-- TABLE: prizes
-- ============================================
CREATE TABLE prizes (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
type prize_type NOT NULL,
name VARCHAR(255) NOT NULL,
description TEXT,
value DECIMAL(10, 2) NOT NULL,
stock INTEGER DEFAULT 0,
probability DECIMAL(5, 4) NOT NULL CHECK (probability >= 0 AND probability <= 1),
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Index pour améliorer les performances
CREATE INDEX idx_prizes_type ON prizes(type);
CREATE INDEX idx_prizes_is_active ON prizes(is_active);
-- ============================================
-- TABLE: tickets
-- ============================================
CREATE TABLE tickets (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
code VARCHAR(50) UNIQUE NOT NULL,
user_id UUID REFERENCES users(id) ON DELETE CASCADE, -- NULL = ticket non joué
prize_id UUID NOT NULL REFERENCES prizes(id) ON DELETE RESTRICT,
status ticket_status, -- NULL = ticket non joué, PENDING/CLAIMED/REJECTED après jeu
played_at TIMESTAMP, -- NULL = ticket non joué, TIMESTAMP = date de jeu
claimed_at TIMESTAMP,
validated_by UUID REFERENCES users(id) ON DELETE SET NULL,
validated_at TIMESTAMP,
rejection_reason TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Index pour améliorer les performances
CREATE INDEX idx_tickets_code ON tickets(code);
CREATE INDEX idx_tickets_user_id ON tickets(user_id);
CREATE INDEX idx_tickets_status ON tickets(status);
CREATE INDEX idx_tickets_prize_id ON tickets(prize_id);
CREATE INDEX idx_tickets_validated_by ON tickets(validated_by);
-- ============================================
-- TABLE: game_settings
-- ============================================
CREATE TABLE game_settings (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
start_date TIMESTAMP NOT NULL,
end_date TIMESTAMP NOT NULL,
is_active BOOLEAN DEFAULT TRUE,
total_tickets INTEGER NOT NULL,
tickets_generated INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- ============================================
-- TRIGGERS
-- ============================================
-- Trigger pour mettre à jour updated_at automatiquement
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = CURRENT_TIMESTAMP;
RETURN NEW;
END;
$$ language 'plpgsql';
CREATE TRIGGER update_users_updated_at BEFORE UPDATE ON users
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_prizes_updated_at BEFORE UPDATE ON prizes
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_tickets_updated_at BEFORE UPDATE ON tickets
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_game_settings_updated_at BEFORE UPDATE ON game_settings
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
-- ============================================
-- INITIAL DATA
-- ============================================
-- Configuration du jeu (concours du 1er janvier au 30 septembre 2025)
INSERT INTO game_settings (start_date, end_date, is_active, total_tickets)
VALUES ('2025-01-01 00:00:00', '2025-09-30 23:59:59', TRUE, 500000);
-- Prix avec probabilités respectant la distribution demandée
-- Total: 500,000 tickets
-- 1. Infuseur à thé (60% = 300,000)
INSERT INTO prizes (type, name, description, value, stock, probability, is_active)
VALUES (
'INFUSEUR',
'Infuseur à thé',
'Un infuseur à thé de qualité supérieure en inox',
39.00,
300000,
0.60,
TRUE
);
-- 2. Boîte de 100g signature (20% = 100,000)
INSERT INTO prizes (type, name, description, value, stock, probability, is_active)
VALUES (
'THE_SIGNATURE',
'Thé Signature 100g',
'Boîte de thé signature 100g - Mélange exclusif Thé Tip Top',
49.00,
100000,
0.20,
TRUE
);
-- 3. Coffret découverte (10% = 50,000)
INSERT INTO prizes (type, name, description, value, stock, probability, is_active)
VALUES (
'COFFRET_DECOUVERTE',
'Coffret Découverte',
'Coffret découverte avec assortiment de 5 thés (39€)',
39.00,
50000,
0.10,
TRUE
);
-- 4. Coffret prestige (6% = 30,000)
INSERT INTO prizes (type, name, description, value, stock, probability, is_active)
VALUES (
'COFFRET_PRESTIGE',
'Coffret Prestige',
'Coffret prestige avec sélection premium de thés rares (69€)',
69.00,
30000,
0.06,
TRUE
);
-- 5. Thé gratuit (4% = 20,000)
INSERT INTO prizes (type, name, description, value, stock, probability, is_active)
VALUES (
'THE_GRATUIT',
'Thé Infusion Gratuit',
'Un thé infusion de votre choix offert en magasin',
0.00,
20000,
0.04,
TRUE
);
-- ============================================
-- VIEWS UTILES
-- ============================================
-- Vue pour les statistiques des prix
CREATE OR REPLACE VIEW prize_statistics AS
SELECT
p.id,
p.name,
p.type,
p.stock AS stock_initial,
COUNT(t.id) AS tickets_used,
(p.stock - COUNT(t.id)) AS stock_remaining,
COUNT(CASE WHEN t.status = 'CLAIMED' THEN 1 END) AS prizes_claimed,
COUNT(CASE WHEN t.status = 'PENDING' THEN 1 END) AS prizes_pending,
COUNT(CASE WHEN t.status = 'REJECTED' THEN 1 END) AS prizes_rejected
FROM prizes p
LEFT JOIN tickets t ON p.id = t.prize_id
GROUP BY p.id, p.name, p.type, p.stock;
-- Vue pour les tickets en attente de validation
CREATE OR REPLACE VIEW pending_tickets AS
SELECT
t.id,
t.code,
t.status,
t.played_at,
u.email AS user_email,
u.first_name || ' ' || u.last_name AS user_name,
u.phone AS user_phone,
p.name AS prize_name,
p.type AS prize_type,
p.value AS prize_value
FROM tickets t
JOIN users u ON t.user_id = u.id
JOIN prizes p ON t.prize_id = p.id
WHERE t.status = 'PENDING'
ORDER BY t.played_at ASC;
-- ============================================
-- COMMENTAIRES
-- ============================================
COMMENT ON TABLE users IS 'Table des utilisateurs (clients, employés, admins)';
COMMENT ON TABLE prizes IS 'Table des prix disponibles dans le jeu';
COMMENT ON TABLE tickets IS 'Table des tickets de jeu joués par les utilisateurs';
COMMENT ON TABLE game_settings IS 'Configuration générale du jeu-concours';
COMMENT ON COLUMN users.role IS 'Rôle: CLIENT, EMPLOYEE, ou ADMIN';
COMMENT ON COLUMN prizes.probability IS 'Probabilité de gagner ce prix (0.0 à 1.0)';
COMMENT ON COLUMN tickets.status IS 'Statut: PENDING (en attente), CLAIMED (réclamé), REJECTED (rejeté)';

247
database/seed.js Normal file
View File

@ -0,0 +1,247 @@
/**
* Script de seed pour insérer des données de test
* Usage: node database/seed.js
*/
import bcrypt from 'bcrypt';
import { pool } from '../db.js';
import { randomUUID } from 'crypto';
const SALT_ROUNDS = 10;
async function seedDatabase() {
try {
console.log('🌱 Démarrage du seed de la base de données...\n');
// ============================================
// 1. SEED USERS
// ============================================
console.log('👥 Création des utilisateurs...');
// Hash des mots de passe
const adminPassword = await bcrypt.hash('Admin123!', SALT_ROUNDS);
const employeePassword = await bcrypt.hash('Employee123!', SALT_ROUNDS);
const clientPassword = await bcrypt.hash('Client123!', SALT_ROUNDS);
// Admin
const adminResult = await pool.query(
`INSERT INTO users (email, password, first_name, last_name, phone, role, is_verified)
VALUES ($1, $2, $3, $4, $5, 'ADMIN', TRUE)
ON CONFLICT (email) DO UPDATE SET role = 'ADMIN'
RETURNING id, email, role`,
['admin@thetiptop.com', adminPassword, 'Admin', 'Principal', '+33123456789']
);
console.log('✅ Admin créé:', adminResult.rows[0].email);
// Employé 1
const employee1Result = await pool.query(
`INSERT INTO users (email, password, first_name, last_name, phone, role, is_verified)
VALUES ($1, $2, $3, $4, $5, 'EMPLOYEE', TRUE)
ON CONFLICT (email) DO UPDATE SET role = 'EMPLOYEE'
RETURNING id, email, role`,
['employee1@thetiptop.com', employeePassword, 'Marie', 'Dupont', '+33198765432']
);
console.log('✅ Employé 1 créé:', employee1Result.rows[0].email);
// Employé 2
const employee2Result = await pool.query(
`INSERT INTO users (email, password, first_name, last_name, phone, role, is_verified)
VALUES ($1, $2, $3, $4, $5, 'EMPLOYEE', TRUE)
ON CONFLICT (email) DO UPDATE SET role = 'EMPLOYEE'
RETURNING id, email, role`,
['employee2@thetiptop.com', employeePassword, 'Pierre', 'Martin', '+33187654321']
);
console.log('✅ Employé 2 créé:', employee2Result.rows[0].email);
// Clients
const clients = [
{
email: 'client1@example.com',
firstName: 'Jean',
lastName: 'Dupuis',
phone: '+33612345678',
},
{
email: 'client2@example.com',
firstName: 'Sophie',
lastName: 'Bernard',
phone: '+33623456789',
},
{
email: 'client3@example.com',
firstName: 'Luc',
lastName: 'Lefevre',
phone: '+33634567890',
},
{
email: 'client4@example.com',
firstName: 'Emma',
lastName: 'Petit',
phone: '+33645678901',
},
{
email: 'client5@example.com',
firstName: 'Thomas',
lastName: 'Robert',
phone: '+33656789012',
},
];
const clientIds = [];
for (const client of clients) {
const result = await pool.query(
`INSERT INTO users (email, password, first_name, last_name, phone, role, is_verified)
VALUES ($1, $2, $3, $4, $5, 'CLIENT', TRUE)
ON CONFLICT (email) DO UPDATE SET role = 'CLIENT'
RETURNING id`,
[
client.email,
clientPassword,
client.firstName,
client.lastName,
client.phone,
]
);
clientIds.push(result.rows[0].id);
console.log(`✅ Client créé: ${client.email}`);
}
console.log(`\n${clients.length + 3} utilisateurs créés avec succès\n`);
// ============================================
// 2. SEED TICKETS
// ============================================
console.log('🎟️ Création des tickets de test...');
// Récupérer les IDs des prix
const prizesResult = await pool.query(
'SELECT id, type FROM prizes ORDER BY type'
);
const prizes = prizesResult.rows;
if (prizes.length === 0) {
console.log('⚠️ Aucun prix trouvé. Exécutez d\'abord le schema.sql');
return;
}
// Créer des tickets avec différents statuts pour chaque client
const ticketStatuses = ['PENDING', 'CLAIMED', 'REJECTED'];
let ticketCount = 0;
for (let i = 0; i < clientIds.length; i++) {
const clientId = clientIds[i];
// Chaque client obtient 3-5 tickets
const numTickets = Math.floor(Math.random() * 3) + 3;
for (let j = 0; j < numTickets; j++) {
// Sélectionner un prix aléatoire
const randomPrize = prizes[Math.floor(Math.random() * prizes.length)];
// Sélectionner un statut (80% PENDING, 10% CLAIMED, 10% REJECTED)
const rand = Math.random();
let status;
if (rand < 0.8) {
status = 'PENDING';
} else if (rand < 0.9) {
status = 'CLAIMED';
} else {
status = 'REJECTED';
}
// Générer un code unique
const ticketCode = `TT-${Date.now()}-${randomUUID().substring(0, 8).toUpperCase()}`;
// Créer le ticket
const insertQuery = `
INSERT INTO tickets (code, user_id, prize_id, status, played_at, claimed_at, validated_by, validated_at, rejection_reason)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
`;
const playedAt = new Date(Date.now() - Math.random() * 30 * 24 * 60 * 60 * 1000); // Dans les 30 derniers jours
let claimedAt = null;
let validatedBy = null;
let validatedAt = null;
let rejectionReason = null;
if (status === 'CLAIMED') {
claimedAt = new Date(playedAt.getTime() + Math.random() * 7 * 24 * 60 * 60 * 1000); // 0-7 jours après
validatedBy = employee1Result.rows[0].id;
validatedAt = claimedAt;
} else if (status === 'REJECTED') {
claimedAt = new Date(playedAt.getTime() + Math.random() * 7 * 24 * 60 * 60 * 1000);
validatedBy = employee1Result.rows[0].id;
validatedAt = claimedAt;
rejectionReason = 'Ticket non conforme ou expiré';
}
await pool.query(insertQuery, [
ticketCode,
clientId,
randomPrize.id,
status,
playedAt,
claimedAt,
validatedBy,
validatedAt,
rejectionReason,
]);
ticketCount++;
}
}
console.log(`${ticketCount} tickets créés avec succès\n`);
// ============================================
// 3. AFFICHER LES STATISTIQUES
// ============================================
console.log('📊 Statistiques de la base de données:\n');
const usersStats = await pool.query(`
SELECT
COUNT(*) as total,
COUNT(CASE WHEN role = 'ADMIN' THEN 1 END) as admins,
COUNT(CASE WHEN role = 'EMPLOYEE' THEN 1 END) as employees,
COUNT(CASE WHEN role = 'CLIENT' THEN 1 END) as clients
FROM users
`);
const ticketsStats = await pool.query(`
SELECT
COUNT(*) as total,
COUNT(CASE WHEN status = 'PENDING' THEN 1 END) as pending,
COUNT(CASE WHEN status = 'CLAIMED' THEN 1 END) as claimed,
COUNT(CASE WHEN status = 'REJECTED' THEN 1 END) as rejected
FROM tickets
`);
console.log('👥 Utilisateurs:');
console.log(` Total: ${usersStats.rows[0].total}`);
console.log(` Admins: ${usersStats.rows[0].admins}`);
console.log(` Employés: ${usersStats.rows[0].employees}`);
console.log(` Clients: ${usersStats.rows[0].clients}`);
console.log('\n🎟 Tickets:');
console.log(` Total: ${ticketsStats.rows[0].total}`);
console.log(` En attente: ${ticketsStats.rows[0].pending}`);
console.log(` Réclamés: ${ticketsStats.rows[0].claimed}`);
console.log(` Rejetés: ${ticketsStats.rows[0].rejected}`);
console.log('\n✅ Seed terminé avec succès!');
console.log('\n🔐 Comptes de test créés:');
console.log(' Admin: admin@thetiptop.com / Admin123!');
console.log(' Employé 1: employee1@thetiptop.com / Employee123!');
console.log(' Employé 2: employee2@thetiptop.com / Employee123!');
console.log(' Clients: client1@example.com à client5@example.com / Client123!');
} catch (error) {
console.error('❌ Erreur lors du seed:', error);
throw error;
} finally {
// Fermer la connexion
await pool.end();
}
}
// Exécuter le seed
seedDatabase();

View File

@ -0,0 +1,64 @@
-- ============================================
-- MISE À JOUR DES NOMS DES LOTS
-- Correction selon les probabilités correctes
-- ============================================
-- 60% des tickets offrent un infuseur à thé (INFUSEUR)
UPDATE prizes
SET
name = 'Infuseur à thé',
description = 'Un infuseur à thé de qualité supérieure en inox',
value = 39.00
WHERE type = 'INFUSEUR';
-- 20% des tickets offrent une boite de 100g d'un thé détox ou d'infusion (THE_GRATUIT)
UPDATE prizes
SET
name = 'Boîte de 100g thé détox ou infusion',
description = 'Une boîte de 100g d''un thé détox ou d''infusion au choix',
value = 0.00,
stock = 100000,
probability = 0.20
WHERE type = 'THE_GRATUIT';
-- 10% des tickets offrent une boite de 100g d'un thé signature (THE_SIGNATURE)
UPDATE prizes
SET
name = 'Boîte de 100g thé signature',
description = 'Une boîte de 100g d''un thé signature - Mélange exclusif',
value = 49.00,
stock = 50000,
probability = 0.10
WHERE type = 'THE_SIGNATURE';
-- 6% des tickets offrent un coffret découverte d'une valeur de 39€ (COFFRET_DECOUVERTE)
UPDATE prizes
SET
name = 'Coffret découverte 39€',
description = 'Coffret découverte avec assortiment de thés d''une valeur de 39€',
value = 39.00,
stock = 30000,
probability = 0.06
WHERE type = 'COFFRET_DECOUVERTE';
-- 4% des tickets offrent un coffret prestige d'une valeur de 69€ (COFFRET_PRESTIGE)
UPDATE prizes
SET
name = 'Coffret découverte 69€',
description = 'Coffret découverte premium avec sélection de thés rares d''une valeur de 69€',
value = 69.00,
stock = 20000,
probability = 0.04
WHERE type = 'COFFRET_PRESTIGE';
-- Vérification
SELECT
type,
name,
description,
value,
stock,
probability,
(probability * 100) || '%' as percentage
FROM prizes
ORDER BY probability DESC;

115
database/update-prizes.js Normal file
View File

@ -0,0 +1,115 @@
/**
* Script pour mettre à jour les noms des lots selon les bonnes probabilités
*/
import { pool } from '../db.js';
async function updatePrizeNames() {
try {
console.log('🔄 Mise à jour des noms des lots...\n');
// 60% - Infuseur à thé
await pool.query(`
UPDATE prizes
SET
name = 'Infuseur à thé',
description = 'Un infuseur à thé de qualité supérieure en inox',
value = 39.00
WHERE type = 'INFUSEUR'
`);
console.log('✅ Infuseur à thé (60%) - Mis à jour');
// 20% - Boîte de 100g thé détox ou infusion
await pool.query(`
UPDATE prizes
SET
name = 'Boîte de 100g thé détox ou infusion',
description = 'Une boîte de 100g d''un thé détox ou d''infusion au choix',
value = 0.00,
stock = 100000,
probability = 0.20
WHERE type = 'THE_GRATUIT'
`);
console.log('✅ Boîte de 100g thé détox ou infusion (20%) - Mis à jour');
// 10% - Boîte de 100g thé signature
await pool.query(`
UPDATE prizes
SET
name = 'Boîte de 100g thé signature',
description = 'Une boîte de 100g d''un thé signature - Mélange exclusif',
value = 49.00,
stock = 50000,
probability = 0.10
WHERE type = 'THE_SIGNATURE'
`);
console.log('✅ Boîte de 100g thé signature (10%) - Mis à jour');
// 6% - Coffret découverte 39€
await pool.query(`
UPDATE prizes
SET
name = 'Coffret découverte 39€',
description = 'Coffret découverte avec assortiment de thés d''une valeur de 39€',
value = 39.00,
stock = 30000,
probability = 0.06
WHERE type = 'COFFRET_DECOUVERTE'
`);
console.log('✅ Coffret découverte 39€ (6%) - Mis à jour');
// 4% - Coffret découverte 69€
await pool.query(`
UPDATE prizes
SET
name = 'Coffret découverte 69€',
description = 'Coffret découverte premium avec sélection de thés rares d''une valeur de 69€',
value = 69.00,
stock = 20000,
probability = 0.04
WHERE type = 'COFFRET_PRESTIGE'
`);
console.log('✅ Coffret découverte 69€ (4%) - Mis à jour');
// Afficher le résultat
console.log('\n📊 Vérification des lots mis à jour:\n');
const result = await pool.query(`
SELECT
type,
name,
description,
value,
stock,
probability,
(probability * 100) || '%' as percentage
FROM prizes
ORDER BY probability DESC
`);
console.log('┌─────────────────────────┬──────────────────────────────────────┬────────┬──────────┬──────────────┐');
console.log('│ TYPE │ NOM │ VALEUR │ STOCK │ PROBABILITÉ │');
console.log('├─────────────────────────┼──────────────────────────────────────┼────────┼──────────┼──────────────┤');
result.rows.forEach(row => {
const type = row.type.padEnd(23);
const name = row.name.substring(0, 36).padEnd(36);
const value = (row.value + '€').padStart(6);
const stock = row.stock.toString().padStart(8);
const prob = row.percentage.padStart(12);
console.log(`${type}${name}${value}${stock}${prob}`);
});
console.log('└─────────────────────────┴──────────────────────────────────────┴────────┴──────────┴──────────────┘');
console.log('\n✅ Mise à jour terminée avec succès!');
} catch (error) {
console.error('❌ Erreur lors de la mise à jour:', error);
throw error;
} finally {
await pool.end();
}
}
// Exécuter la mise à jour
updatePrizeNames();

24
db.js
View File

@ -1,23 +1,21 @@
import dotenv from "dotenv";
import pkg from "pg";
// Charger les variables d'environnement depuis .env
dotenv.config();
import config from "./src/config/env.js";
const { Pool } = pkg;
// Log de debug pour vérifier que les variables sont bien lues
console.log("🧩 DB Config →", {
host: process.env.DB_HOST,
user: process.env.DB_USER,
pass: process.env.DB_PASS,
name: process.env.DB_NAME,
host: config.db.host,
port: config.db.port,
user: config.db.user,
pass: config.db.password ? '***' : undefined,
database: config.db.database,
});
export const pool = new Pool({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_NAME,
port: 5432,
host: config.db.host,
port: config.db.port,
user: config.db.user,
password: config.db.password,
database: config.db.database,
});

View File

@ -1,24 +1,64 @@
import express from "express";
import cors from "cors";
import dotenv from "dotenv";
import helmet from "helmet";
import morgan from "morgan";
import client from "prom-client";
import config from "./src/config/env.js";
import { pool } from "./db.js";
import { errorHandler } from "./src/middleware/errorHandler.js";
// Import routes
import authRoutes from "./src/routes/auth.routes.js";
import userRoutes from "./src/routes/user.routes.js";
import gameRoutes from "./src/routes/game.routes.js";
import employeeRoutes from "./src/routes/employee.routes.js";
import adminRoutes from "./src/routes/admin.routes.js";
import drawRoutes from "./src/routes/draw.routes.js";
dotenv.config();
const app = express();
// CORS doit être configuré AVANT helmet
app.use(
cors({
origin: ["http://localhost:3000", "https://dsp5-archi-o24a-15m-g3.fr"],
origin: function (origin, callback) {
const allowedOrigins = [
"http://localhost:3000",
"http://localhost:3001",
"http://localhost:3002",
"http://localhost:3003",
"http://localhost:3004",
"http://localhost:3005",
"https://dsp5-archi-o24a-15m-g3.fr",
"https://dev.dsp5-archi-o24a-15m-g3.fr"
];
// Autoriser les requêtes sans origin (Postman, curl, etc.)
if (!origin) return callback(null, true);
if (allowedOrigins.indexOf(origin) !== -1) {
callback(null, true);
} else {
callback(null, true); // En dev, on autorise tout
}
},
credentials: true,
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'],
exposedHeaders: ['Content-Length', 'X-Request-Id'],
maxAge: 86400, // 24h
})
);
app.use(helmet());
// Helmet avec configuration moins restrictive
app.use(helmet({
crossOriginResourcePolicy: { policy: "cross-origin" },
crossOriginOpenerPolicy: { policy: "same-origin-allow-popups" },
}));
app.use(morgan("tiny"));
app.use(express.json());
// Servir les fichiers statiques depuis le dossier public
app.use('/public', express.static('public'));
// ✅ Route racine (pour test ou monitoring)
app.get("/", (req, res) => {
@ -42,8 +82,19 @@ app.get("/metrics", async (req, res) => {
res.end(await client.register.metrics());
});
// API Routes
app.use("/api/auth", authRoutes);
app.use("/api/users", userRoutes);
app.use("/api/game", gameRoutes);
app.use("/api/employee", employeeRoutes);
app.use("/api/admin", adminRoutes);
app.use("/api/draw", drawRoutes);
// Error handler (doit être après les routes)
app.use(errorHandler);
// Lancement serveur
const PORT = process.env.PORT || 4000;
const PORT = config.server.port;
app.listen(PORT, "0.0.0.0", () => {
console.log(`🚀 Backend lancé sur 0.0.0.0:${PORT}`);
});

16
node_modules/.bin/bcrypt generated vendored Normal file
View File

@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../bcryptjs/bin/bcrypt" "$@"
else
exec node "$basedir/../bcryptjs/bin/bcrypt" "$@"
fi

17
node_modules/.bin/bcrypt.cmd generated vendored Normal file
View File

@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\bcryptjs\bin\bcrypt" %*

28
node_modules/.bin/bcrypt.ps1 generated vendored Normal file
View File

@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../bcryptjs/bin/bcrypt" $args
} else {
& "$basedir/node$exe" "$basedir/../bcryptjs/bin/bcrypt" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../bcryptjs/bin/bcrypt" $args
} else {
& "node$exe" "$basedir/../bcryptjs/bin/bcrypt" $args
}
$ret=$LASTEXITCODE
}
exit $ret

16
node_modules/.bin/rimraf generated vendored Normal file
View File

@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../rimraf/dist/esm/bin.mjs" "$@"
else
exec node "$basedir/../rimraf/dist/esm/bin.mjs" "$@"
fi

17
node_modules/.bin/rimraf.cmd generated vendored Normal file
View File

@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\rimraf\dist\esm\bin.mjs" %*

28
node_modules/.bin/rimraf.ps1 generated vendored Normal file
View File

@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../rimraf/dist/esm/bin.mjs" $args
} else {
& "$basedir/node$exe" "$basedir/../rimraf/dist/esm/bin.mjs" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../rimraf/dist/esm/bin.mjs" $args
} else {
& "node$exe" "$basedir/../rimraf/dist/esm/bin.mjs" $args
}
$ret=$LASTEXITCODE
}
exit $ret

16
node_modules/.bin/uuid generated vendored Normal file
View File

@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../uuid/dist-node/bin/uuid" "$@"
else
exec node "$basedir/../uuid/dist-node/bin/uuid" "$@"
fi

17
node_modules/.bin/uuid.cmd generated vendored Normal file
View File

@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\uuid\dist-node\bin\uuid" %*

28
node_modules/.bin/uuid.ps1 generated vendored Normal file
View File

@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../uuid/dist-node/bin/uuid" $args
} else {
& "$basedir/node$exe" "$basedir/../uuid/dist-node/bin/uuid" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../uuid/dist-node/bin/uuid" $args
} else {
& "node$exe" "$basedir/../uuid/dist-node/bin/uuid" $args
}
$ret=$LASTEXITCODE
}
exit $ret

374
node_modules/.package-lock.json generated vendored
View File

@ -720,7 +720,6 @@
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
"dev": true,
"license": "ISC",
"dependencies": {
"string-width": "^5.1.2",
@ -1279,7 +1278,6 @@
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
"dev": true,
"license": "MIT",
"optional": true,
"engines": {
@ -1503,6 +1501,15 @@
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
}
},
"node_modules/agent-base": {
"version": "7.1.4",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
"integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
"license": "MIT",
"engines": {
"node": ">= 14"
}
},
"node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@ -1540,7 +1547,6 @@
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
"integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
@ -1553,7 +1559,6 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
@ -1703,7 +1708,26 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true,
"license": "MIT"
},
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
"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/base64url": {
@ -1757,6 +1781,24 @@
"node": ">= 18"
}
},
"node_modules/bcryptjs": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-3.0.3.tgz",
"integrity": "sha512-GlF5wPWnSa/X5LKM1o0wz0suXIINz1iHRLvTS+sLyi7XPbe5ycmYI3DlZqVGZZtDgl4DmasFg7gOB3JYbphV5g==",
"license": "BSD-3-Clause",
"bin": {
"bcrypt": "bin/bcrypt"
}
},
"node_modules/bignumber.js": {
"version": "9.3.1",
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz",
"integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==",
"license": "MIT",
"engines": {
"node": "*"
}
},
"node_modules/binary-extensions": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
@ -2154,7 +2196,6 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
@ -2167,7 +2208,6 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true,
"license": "MIT"
},
"node_modules/combined-stream": {
@ -2270,7 +2310,6 @@
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dev": true,
"license": "MIT",
"dependencies": {
"path-key": "^3.1.0",
@ -2281,6 +2320,25 @@
"node": ">= 8"
}
},
"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": "4.1.0",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
"integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/kossnocorp"
}
},
"node_modules/debug": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
@ -2400,7 +2458,6 @@
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
"dev": true,
"license": "MIT"
},
"node_modules/ecdsa-sig-formatter": {
@ -2442,7 +2499,6 @@
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
"dev": true,
"license": "MIT"
},
"node_modules/encodeurl": {
@ -2870,6 +2926,12 @@
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"license": "MIT"
},
"node_modules/extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
"license": "MIT"
},
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@ -2908,6 +2970,29 @@
"bser": "2.1.1"
}
},
"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",
@ -2993,7 +3078,6 @@
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
"integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
"dev": true,
"license": "ISC",
"dependencies": {
"cross-spawn": "^7.0.6",
@ -3046,6 +3130,18 @@
"node": ">= 0.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==",
"license": "MIT",
"dependencies": {
"fetch-blob": "^3.1.2"
},
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/formidable": {
"version": "3.5.4",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.4.tgz",
@ -3098,6 +3194,35 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/gaxios": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.3.tgz",
"integrity": "sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ==",
"license": "Apache-2.0",
"dependencies": {
"extend": "^3.0.2",
"https-proxy-agent": "^7.0.1",
"node-fetch": "^3.3.2",
"rimraf": "^5.0.1"
},
"engines": {
"node": ">=18"
}
},
"node_modules/gcp-metadata": {
"version": "8.1.2",
"resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz",
"integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==",
"license": "Apache-2.0",
"dependencies": {
"gaxios": "^7.0.0",
"google-logging-utils": "^1.0.0",
"json-bigint": "^1.0.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/gensync": {
"version": "1.0.0-beta.2",
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
@ -3182,7 +3307,6 @@
"version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
"dev": true,
"license": "ISC",
"dependencies": {
"foreground-child": "^3.1.0",
@ -3216,7 +3340,6 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
@ -3226,7 +3349,6 @@
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"dev": true,
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
@ -3251,6 +3373,54 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/google-auth-library": {
"version": "10.5.0",
"resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.5.0.tgz",
"integrity": "sha512-7ABviyMOlX5hIVD60YOfHw4/CxOfBhyduaYB+wbFWCWoni4N7SLcV46hrVRktuBbZjFC9ONyqamZITN7q3n32w==",
"license": "Apache-2.0",
"dependencies": {
"base64-js": "^1.3.0",
"ecdsa-sig-formatter": "^1.0.11",
"gaxios": "^7.0.0",
"gcp-metadata": "^8.0.0",
"google-logging-utils": "^1.0.0",
"gtoken": "^8.0.0",
"jws": "^4.0.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/google-auth-library/node_modules/jwa": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz",
"integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==",
"license": "MIT",
"dependencies": {
"buffer-equal-constant-time": "^1.0.1",
"ecdsa-sig-formatter": "1.0.11",
"safe-buffer": "^5.0.1"
}
},
"node_modules/google-auth-library/node_modules/jws": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz",
"integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==",
"license": "MIT",
"dependencies": {
"jwa": "^2.0.0",
"safe-buffer": "^5.0.1"
}
},
"node_modules/google-logging-utils": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz",
"integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==",
"license": "Apache-2.0",
"engines": {
"node": ">=14"
}
},
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
@ -3270,6 +3440,40 @@
"dev": true,
"license": "ISC"
},
"node_modules/gtoken": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/gtoken/-/gtoken-8.0.0.tgz",
"integrity": "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw==",
"license": "MIT",
"dependencies": {
"gaxios": "^7.0.0",
"jws": "^4.0.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/gtoken/node_modules/jwa": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz",
"integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==",
"license": "MIT",
"dependencies": {
"buffer-equal-constant-time": "^1.0.1",
"ecdsa-sig-formatter": "1.0.11",
"safe-buffer": "^5.0.1"
}
},
"node_modules/gtoken/node_modules/jws": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz",
"integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==",
"license": "MIT",
"dependencies": {
"jwa": "^2.0.0",
"safe-buffer": "^5.0.1"
}
},
"node_modules/has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
@ -3361,6 +3565,19 @@
"node": ">= 0.8"
}
},
"node_modules/https-proxy-agent": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
"integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
"license": "MIT",
"dependencies": {
"agent-base": "^7.1.2",
"debug": "4"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/human-signals": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
@ -3508,7 +3725,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@ -3570,7 +3786,6 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
"dev": true,
"license": "ISC"
},
"node_modules/istanbul-lib-coverage": {
@ -3671,7 +3886,6 @@
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
"integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
"dev": true,
"license": "BlueOak-1.0.0",
"dependencies": {
"@isaacs/cliui": "^8.0.2"
@ -4319,6 +4533,15 @@
"node": ">=6"
}
},
"node_modules/json-bigint": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz",
"integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==",
"license": "MIT",
"dependencies": {
"bignumber.js": "^9.0.0"
}
},
"node_modules/json-buffer": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
@ -4667,7 +4890,6 @@
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
"dev": true,
"license": "ISC",
"engines": {
"node": ">=16 || 14 >=14.17"
@ -4763,6 +4985,44 @@
"node": "^18 || ^20 || >= 21"
}
},
"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",
"engines": {
"node": ">=10.5.0"
}
},
"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==",
"license": "MIT",
"dependencies": {
"data-uri-to-buffer": "^4.0.0",
"fetch-blob": "^3.1.4",
"formdata-polyfill": "^4.0.10"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/node-fetch"
}
},
"node_modules/node-gyp-build": {
"version": "4.8.4",
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
@ -4788,6 +5048,15 @@
"dev": true,
"license": "MIT"
},
"node_modules/nodemailer": {
"version": "7.0.10",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.10.tgz",
"integrity": "sha512-Us/Se1WtT0ylXgNFfyFSx4LElllVLJXQjWi2Xz17xWw7amDKO2MLtFnVp1WACy7GkVGs+oBlRopVNUzlrGSw1w==",
"license": "MIT-0",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/nodemon": {
"version": "3.1.10",
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.10.tgz",
@ -4977,7 +5246,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
"integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
"dev": true,
"license": "BlueOak-1.0.0"
},
"node_modules/parent-module": {
@ -5115,7 +5383,6 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@ -5125,7 +5392,6 @@
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
"integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
"dev": true,
"license": "BlueOak-1.0.0",
"dependencies": {
"lru-cache": "^10.2.0",
@ -5142,7 +5408,6 @@
"version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
"dev": true,
"license": "ISC"
},
"node_modules/path-to-regexp": {
@ -5612,6 +5877,21 @@
"node": ">=4"
}
},
"node_modules/rimraf": {
"version": "5.0.10",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz",
"integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==",
"license": "ISC",
"dependencies": {
"glob": "^10.3.7"
},
"bin": {
"rimraf": "dist/esm/bin.mjs"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/router": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
@ -5713,7 +5993,6 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"dev": true,
"license": "MIT",
"dependencies": {
"shebang-regex": "^3.0.0"
@ -5726,7 +6005,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@ -5808,7 +6086,6 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
"dev": true,
"license": "ISC",
"engines": {
"node": ">=14"
@ -5950,7 +6227,6 @@
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
"dev": true,
"license": "MIT",
"dependencies": {
"eastasianwidth": "^0.2.0",
@ -5969,7 +6245,6 @@
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"license": "MIT",
"dependencies": {
"emoji-regex": "^8.0.0",
@ -5984,7 +6259,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@ -5994,14 +6268,12 @@
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true,
"license": "MIT"
},
"node_modules/string-width-cjs/node_modules/strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"license": "MIT",
"dependencies": {
"ansi-regex": "^5.0.1"
@ -6014,7 +6286,6 @@
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz",
"integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==",
"dev": true,
"license": "MIT",
"dependencies": {
"ansi-regex": "^6.0.1"
@ -6031,7 +6302,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"license": "MIT",
"dependencies": {
"ansi-regex": "^5.0.1"
@ -6044,7 +6314,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@ -6408,6 +6677,19 @@
"node": ">= 0.4.0"
}
},
"node_modules/uuid": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.0.tgz",
"integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==",
"funding": [
"https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan"
],
"license": "MIT",
"bin": {
"uuid": "dist-node/bin/uuid"
}
},
"node_modules/v8-to-istanbul": {
"version": "9.3.0",
"resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz",
@ -6442,11 +6724,19 @@
"makeerror": "1.0.12"
}
},
"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"
}
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"dev": true,
"license": "ISC",
"dependencies": {
"isexe": "^2.0.0"
@ -6472,7 +6762,6 @@
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"ansi-styles": "^6.1.0",
@ -6491,7 +6780,6 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"ansi-styles": "^4.0.0",
@ -6509,7 +6797,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@ -6519,14 +6806,12 @@
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true,
"license": "MIT"
},
"node_modules/wrap-ansi-cjs/node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"license": "MIT",
"dependencies": {
"emoji-regex": "^8.0.0",
@ -6541,7 +6826,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"license": "MIT",
"dependencies": {
"ansi-regex": "^5.0.1"
@ -6554,7 +6838,6 @@
"version": "6.2.3",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz",
"integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
@ -6695,6 +6978,15 @@
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/zod": {
"version": "4.1.12",
"resolved": "https://registry.npmjs.org/zod/-/zod-4.1.12.tgz",
"integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
}
}
}

22
node_modules/agent-base/LICENSE generated vendored Normal file
View File

@ -0,0 +1,22 @@
(The MIT License)
Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

69
node_modules/agent-base/README.md generated vendored Normal file
View File

@ -0,0 +1,69 @@
agent-base
==========
### Turn a function into an [`http.Agent`][http.Agent] instance
This module is a thin wrapper around the base `http.Agent` class.
It provides an abstract class that must define a `connect()` function,
which is responsible for creating the underlying socket that the HTTP
client requests will use.
The `connect()` function may return an arbitrary `Duplex` stream, or
another `http.Agent` instance to delegate the request to, and may be
asynchronous (by defining an `async` function).
Instances of this agent can be used with the `http` and `https`
modules. To differentiate, the options parameter in the `connect()`
function includes a `secureEndpoint` property, which can be checked
to determine what type of socket should be returned.
#### Some subclasses:
Here are some more interesting uses of `agent-base`.
Send a pull request to list yours!
* [`http-proxy-agent`][http-proxy-agent]: An HTTP(s) proxy `http.Agent` implementation for HTTP endpoints
* [`https-proxy-agent`][https-proxy-agent]: An HTTP(s) proxy `http.Agent` implementation for HTTPS endpoints
* [`pac-proxy-agent`][pac-proxy-agent]: A PAC file proxy `http.Agent` implementation for HTTP and HTTPS
* [`socks-proxy-agent`][socks-proxy-agent]: A SOCKS proxy `http.Agent` implementation for HTTP and HTTPS
Example
-------
Here's a minimal example that creates a new `net.Socket` or `tls.Socket`
based on the `secureEndpoint` property. This agent can be used with both
the `http` and `https` modules.
```ts
import * as net from 'net';
import * as tls from 'tls';
import * as http from 'http';
import { Agent } from 'agent-base';
class MyAgent extends Agent {
connect(req, opts) {
// `secureEndpoint` is true when using the "https" module
if (opts.secureEndpoint) {
return tls.connect(opts);
} else {
return net.connect(opts);
}
}
});
// Keep alive enabled means that `connect()` will only be
// invoked when a new connection needs to be created
const agent = new MyAgent({ keepAlive: true });
// Pass the `agent` option when creating the HTTP request
http.get('http://nodejs.org/api/', { agent }, (res) => {
console.log('"response" event!', res.headers);
res.pipe(process.stdout);
});
```
[http-proxy-agent]: ../http-proxy-agent
[https-proxy-agent]: ../https-proxy-agent
[pac-proxy-agent]: ../pac-proxy-agent
[socks-proxy-agent]: ../socks-proxy-agent
[http.Agent]: https://nodejs.org/api/http.html#http_class_http_agent

15
node_modules/agent-base/dist/helpers.d.ts generated vendored Normal file
View File

@ -0,0 +1,15 @@
/// <reference types="node" />
/// <reference types="node" />
/// <reference types="node" />
/// <reference types="node" />
/// <reference types="node" />
import * as http from 'http';
import * as https from 'https';
import type { Readable } from 'stream';
export type ThenableRequest = http.ClientRequest & {
then: Promise<http.IncomingMessage>['then'];
};
export declare function toBuffer(stream: Readable): Promise<Buffer>;
export declare function json(stream: Readable): Promise<any>;
export declare function req(url: string | URL, opts?: https.RequestOptions): ThenableRequest;
//# sourceMappingURL=helpers.d.ts.map

1
node_modules/agent-base/dist/helpers.d.ts.map generated vendored Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":";;;;;AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAEvC,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,aAAa,GAAG;IAClD,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;CAC5C,CAAC;AAEF,wBAAsB,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAQhE;AAGD,wBAAsB,IAAI,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAUzD;AAED,wBAAgB,GAAG,CAClB,GAAG,EAAE,MAAM,GAAG,GAAG,EACjB,IAAI,GAAE,KAAK,CAAC,cAAmB,GAC7B,eAAe,CAcjB"}

66
node_modules/agent-base/dist/helpers.js generated vendored Normal file
View File

@ -0,0 +1,66 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.req = exports.json = exports.toBuffer = void 0;
const http = __importStar(require("http"));
const https = __importStar(require("https"));
async function toBuffer(stream) {
let length = 0;
const chunks = [];
for await (const chunk of stream) {
length += chunk.length;
chunks.push(chunk);
}
return Buffer.concat(chunks, length);
}
exports.toBuffer = toBuffer;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async function json(stream) {
const buf = await toBuffer(stream);
const str = buf.toString('utf8');
try {
return JSON.parse(str);
}
catch (_err) {
const err = _err;
err.message += ` (input: ${str})`;
throw err;
}
}
exports.json = json;
function req(url, opts = {}) {
const href = typeof url === 'string' ? url : url.href;
const req = (href.startsWith('https:') ? https : http).request(url, opts);
const promise = new Promise((resolve, reject) => {
req
.once('response', resolve)
.once('error', reject)
.end();
});
req.then = promise.then.bind(promise);
return req;
}
exports.req = req;
//# sourceMappingURL=helpers.js.map

1
node_modules/agent-base/dist/helpers.js.map generated vendored Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAA6B;AAC7B,6CAA+B;AAOxB,KAAK,UAAU,QAAQ,CAAC,MAAgB;IAC9C,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE;QACjC,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC;QACvB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;KACnB;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACtC,CAAC;AARD,4BAQC;AAED,8DAA8D;AACvD,KAAK,UAAU,IAAI,CAAC,MAAgB;IAC1C,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACjC,IAAI;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;KACvB;IAAC,OAAO,IAAa,EAAE;QACvB,MAAM,GAAG,GAAG,IAAa,CAAC;QAC1B,GAAG,CAAC,OAAO,IAAI,YAAY,GAAG,GAAG,CAAC;QAClC,MAAM,GAAG,CAAC;KACV;AACF,CAAC;AAVD,oBAUC;AAED,SAAgB,GAAG,CAClB,GAAiB,EACjB,OAA6B,EAAE;IAE/B,MAAM,IAAI,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;IACtD,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,CAC7D,GAAG,EACH,IAAI,CACe,CAAC;IACrB,MAAM,OAAO,GAAG,IAAI,OAAO,CAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrE,GAAG;aACD,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC;aACzB,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC;aACrB,GAAG,EAAqB,CAAC;IAC5B,CAAC,CAAC,CAAC;IACH,GAAG,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACtC,OAAO,GAAG,CAAC;AACZ,CAAC;AAjBD,kBAiBC"}

41
node_modules/agent-base/dist/index.d.ts generated vendored Normal file
View File

@ -0,0 +1,41 @@
/// <reference types="node" />
/// <reference types="node" />
/// <reference types="node" />
/// <reference types="node" />
import * as net from 'net';
import * as tls from 'tls';
import * as http from 'http';
import type { Duplex } from 'stream';
export * from './helpers';
interface HttpConnectOpts extends net.TcpNetConnectOpts {
secureEndpoint: false;
protocol?: string;
}
interface HttpsConnectOpts extends tls.ConnectionOptions {
secureEndpoint: true;
protocol?: string;
port: number;
}
export type AgentConnectOpts = HttpConnectOpts | HttpsConnectOpts;
declare const INTERNAL: unique symbol;
export declare abstract class Agent extends http.Agent {
private [INTERNAL];
options: Partial<net.TcpNetConnectOpts & tls.ConnectionOptions>;
keepAlive: boolean;
constructor(opts?: http.AgentOptions);
abstract connect(req: http.ClientRequest, options: AgentConnectOpts): Promise<Duplex | http.Agent> | Duplex | http.Agent;
/**
* Determine whether this is an `http` or `https` request.
*/
isSecureEndpoint(options?: AgentConnectOpts): boolean;
private incrementSockets;
private decrementSockets;
getName(options?: AgentConnectOpts): string;
createSocket(req: http.ClientRequest, options: AgentConnectOpts, cb: (err: Error | null, s?: Duplex) => void): void;
createConnection(): Duplex;
get defaultPort(): number;
set defaultPort(v: number);
get protocol(): string;
set protocol(v: string);
}
//# sourceMappingURL=index.d.ts.map

1
node_modules/agent-base/dist/index.d.ts.map generated vendored Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;AAAA,OAAO,KAAK,GAAG,MAAM,KAAK,CAAC;AAC3B,OAAO,KAAK,GAAG,MAAM,KAAK,CAAC;AAC3B,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAErC,cAAc,WAAW,CAAC;AAE1B,UAAU,eAAgB,SAAQ,GAAG,CAAC,iBAAiB;IACtD,cAAc,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,gBAAiB,SAAQ,GAAG,CAAC,iBAAiB;IACvD,cAAc,EAAE,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,gBAAgB,GAAG,eAAe,GAAG,gBAAgB,CAAC;AAElE,QAAA,MAAM,QAAQ,eAAmC,CAAC;AAQlD,8BAAsB,KAAM,SAAQ,IAAI,CAAC,KAAK;IAC7C,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAgB;IAGlC,OAAO,EAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACjE,SAAS,EAAG,OAAO,CAAC;gBAER,IAAI,CAAC,EAAE,IAAI,CAAC,YAAY;IAKpC,QAAQ,CAAC,OAAO,CACf,GAAG,EAAE,IAAI,CAAC,aAAa,EACvB,OAAO,EAAE,gBAAgB,GACvB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,KAAK;IAErD;;OAEG;IACH,gBAAgB,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO;IAqCrD,OAAO,CAAC,gBAAgB;IAqBxB,OAAO,CAAC,gBAAgB;IAmBxB,OAAO,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,MAAM;IAU3C,YAAY,CACX,GAAG,EAAE,IAAI,CAAC,aAAa,EACvB,OAAO,EAAE,gBAAgB,EACzB,EAAE,EAAE,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI;IAgC5C,gBAAgB,IAAI,MAAM;IAW1B,IAAI,WAAW,IAAI,MAAM,CAKxB;IAED,IAAI,WAAW,CAAC,CAAC,EAAE,MAAM,EAIxB;IAED,IAAI,QAAQ,IAAI,MAAM,CAKrB;IAED,IAAI,QAAQ,CAAC,CAAC,EAAE,MAAM,EAIrB;CACD"}

178
node_modules/agent-base/dist/index.js generated vendored Normal file
View File

@ -0,0 +1,178 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Agent = void 0;
const net = __importStar(require("net"));
const http = __importStar(require("http"));
const https_1 = require("https");
__exportStar(require("./helpers"), exports);
const INTERNAL = Symbol('AgentBaseInternalState');
class Agent extends http.Agent {
constructor(opts) {
super(opts);
this[INTERNAL] = {};
}
/**
* Determine whether this is an `http` or `https` request.
*/
isSecureEndpoint(options) {
if (options) {
// First check the `secureEndpoint` property explicitly, since this
// means that a parent `Agent` is "passing through" to this instance.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
if (typeof options.secureEndpoint === 'boolean') {
return options.secureEndpoint;
}
// If no explicit `secure` endpoint, check if `protocol` property is
// set. This will usually be the case since using a full string URL
// or `URL` instance should be the most common usage.
if (typeof options.protocol === 'string') {
return options.protocol === 'https:';
}
}
// Finally, if no `protocol` property was set, then fall back to
// checking the stack trace of the current call stack, and try to
// detect the "https" module.
const { stack } = new Error();
if (typeof stack !== 'string')
return false;
return stack
.split('\n')
.some((l) => l.indexOf('(https.js:') !== -1 ||
l.indexOf('node:https:') !== -1);
}
// In order to support async signatures in `connect()` and Node's native
// connection pooling in `http.Agent`, the array of sockets for each origin
// has to be updated synchronously. This is so the length of the array is
// accurate when `addRequest()` is next called. We achieve this by creating a
// fake socket and adding it to `sockets[origin]` and incrementing
// `totalSocketCount`.
incrementSockets(name) {
// If `maxSockets` and `maxTotalSockets` are both Infinity then there is no
// need to create a fake socket because Node.js native connection pooling
// will never be invoked.
if (this.maxSockets === Infinity && this.maxTotalSockets === Infinity) {
return null;
}
// All instances of `sockets` are expected TypeScript errors. The
// alternative is to add it as a private property of this class but that
// will break TypeScript subclassing.
if (!this.sockets[name]) {
// @ts-expect-error `sockets` is readonly in `@types/node`
this.sockets[name] = [];
}
const fakeSocket = new net.Socket({ writable: false });
this.sockets[name].push(fakeSocket);
// @ts-expect-error `totalSocketCount` isn't defined in `@types/node`
this.totalSocketCount++;
return fakeSocket;
}
decrementSockets(name, socket) {
if (!this.sockets[name] || socket === null) {
return;
}
const sockets = this.sockets[name];
const index = sockets.indexOf(socket);
if (index !== -1) {
sockets.splice(index, 1);
// @ts-expect-error `totalSocketCount` isn't defined in `@types/node`
this.totalSocketCount--;
if (sockets.length === 0) {
// @ts-expect-error `sockets` is readonly in `@types/node`
delete this.sockets[name];
}
}
}
// In order to properly update the socket pool, we need to call `getName()` on
// the core `https.Agent` if it is a secureEndpoint.
getName(options) {
const secureEndpoint = this.isSecureEndpoint(options);
if (secureEndpoint) {
// @ts-expect-error `getName()` isn't defined in `@types/node`
return https_1.Agent.prototype.getName.call(this, options);
}
// @ts-expect-error `getName()` isn't defined in `@types/node`
return super.getName(options);
}
createSocket(req, options, cb) {
const connectOpts = {
...options,
secureEndpoint: this.isSecureEndpoint(options),
};
const name = this.getName(connectOpts);
const fakeSocket = this.incrementSockets(name);
Promise.resolve()
.then(() => this.connect(req, connectOpts))
.then((socket) => {
this.decrementSockets(name, fakeSocket);
if (socket instanceof http.Agent) {
try {
// @ts-expect-error `addRequest()` isn't defined in `@types/node`
return socket.addRequest(req, connectOpts);
}
catch (err) {
return cb(err);
}
}
this[INTERNAL].currentSocket = socket;
// @ts-expect-error `createSocket()` isn't defined in `@types/node`
super.createSocket(req, options, cb);
}, (err) => {
this.decrementSockets(name, fakeSocket);
cb(err);
});
}
createConnection() {
const socket = this[INTERNAL].currentSocket;
this[INTERNAL].currentSocket = undefined;
if (!socket) {
throw new Error('No socket was returned in the `connect()` function');
}
return socket;
}
get defaultPort() {
return (this[INTERNAL].defaultPort ??
(this.protocol === 'https:' ? 443 : 80));
}
set defaultPort(v) {
if (this[INTERNAL]) {
this[INTERNAL].defaultPort = v;
}
}
get protocol() {
return (this[INTERNAL].protocol ??
(this.isSecureEndpoint() ? 'https:' : 'http:'));
}
set protocol(v) {
if (this[INTERNAL]) {
this[INTERNAL].protocol = v;
}
}
}
exports.Agent = Agent;
//# sourceMappingURL=index.js.map

1
node_modules/agent-base/dist/index.js.map generated vendored Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,yCAA2B;AAE3B,2CAA6B;AAC7B,iCAA4C;AAG5C,4CAA0B;AAe1B,MAAM,QAAQ,GAAG,MAAM,CAAC,wBAAwB,CAAC,CAAC;AAQlD,MAAsB,KAAM,SAAQ,IAAI,CAAC,KAAK;IAO7C,YAAY,IAAwB;QACnC,KAAK,CAAC,IAAI,CAAC,CAAC;QACZ,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;IACrB,CAAC;IAOD;;OAEG;IACH,gBAAgB,CAAC,OAA0B;QAC1C,IAAI,OAAO,EAAE;YACZ,mEAAmE;YACnE,qEAAqE;YACrE,8DAA8D;YAC9D,IAAI,OAAQ,OAAe,CAAC,cAAc,KAAK,SAAS,EAAE;gBACzD,OAAO,OAAO,CAAC,cAAc,CAAC;aAC9B;YAED,oEAAoE;YACpE,mEAAmE;YACnE,qDAAqD;YACrD,IAAI,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE;gBACzC,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC;aACrC;SACD;QAED,gEAAgE;QAChE,iEAAiE;QACjE,6BAA6B;QAC7B,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,KAAK,EAAE,CAAC;QAC9B,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QAC5C,OAAO,KAAK;aACV,KAAK,CAAC,IAAI,CAAC;aACX,IAAI,CACJ,CAAC,CAAC,EAAE,EAAE,CACL,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;YAC9B,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAChC,CAAC;IACJ,CAAC;IAED,wEAAwE;IACxE,2EAA2E;IAC3E,yEAAyE;IACzE,6EAA6E;IAC7E,kEAAkE;IAClE,sBAAsB;IACd,gBAAgB,CAAC,IAAY;QACpC,2EAA2E;QAC3E,yEAAyE;QACzE,yBAAyB;QACzB,IAAI,IAAI,CAAC,UAAU,KAAK,QAAQ,IAAI,IAAI,CAAC,eAAe,KAAK,QAAQ,EAAE;YACtE,OAAO,IAAI,CAAC;SACZ;QACD,iEAAiE;QACjE,wEAAwE;QACxE,qCAAqC;QACrC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;YACxB,0DAA0D;YAC1D,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;SACxB;QACD,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;QACtD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAkB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACtD,qEAAqE;QACrE,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACxB,OAAO,UAAU,CAAC;IACnB,CAAC;IAEO,gBAAgB,CAAC,IAAY,EAAE,MAAyB;QAC/D,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,MAAM,KAAK,IAAI,EAAE;YAC3C,OAAO;SACP;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAiB,CAAC;QACnD,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACtC,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE;YACjB,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YACzB,sEAAsE;YACtE,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACxB,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE;gBACzB,0DAA0D;gBAC1D,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;aAC1B;SACD;IACF,CAAC;IAED,8EAA8E;IAC9E,oDAAoD;IACpD,OAAO,CAAC,OAA0B;QACjC,MAAM,cAAc,GAAG,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;QACtD,IAAI,cAAc,EAAE;YACnB,8DAA8D;YAC9D,OAAO,aAAU,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;SACxD;QACD,8DAA8D;QAC9D,OAAO,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;IAED,YAAY,CACX,GAAuB,EACvB,OAAyB,EACzB,EAA2C;QAE3C,MAAM,WAAW,GAAG;YACnB,GAAG,OAAO;YACV,cAAc,EAAE,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC;SAC9C,CAAC;QACF,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QACvC,MAAM,UAAU,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAC/C,OAAO,CAAC,OAAO,EAAE;aACf,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;aAC1C,IAAI,CACJ,CAAC,MAAM,EAAE,EAAE;YACV,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;YACxC,IAAI,MAAM,YAAY,IAAI,CAAC,KAAK,EAAE;gBACjC,IAAI;oBACH,iEAAiE;oBACjE,OAAO,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;iBAC3C;gBAAC,OAAO,GAAY,EAAE;oBACtB,OAAO,EAAE,CAAC,GAAY,CAAC,CAAC;iBACxB;aACD;YACD,IAAI,CAAC,QAAQ,CAAC,CAAC,aAAa,GAAG,MAAM,CAAC;YACtC,mEAAmE;YACnE,KAAK,CAAC,YAAY,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;QACtC,CAAC,EACD,CAAC,GAAG,EAAE,EAAE;YACP,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;YACxC,EAAE,CAAC,GAAG,CAAC,CAAC;QACT,CAAC,CACD,CAAC;IACJ,CAAC;IAED,gBAAgB;QACf,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,aAAa,CAAC;QAC5C,IAAI,CAAC,QAAQ,CAAC,CAAC,aAAa,GAAG,SAAS,CAAC;QACzC,IAAI,CAAC,MAAM,EAAE;YACZ,MAAM,IAAI,KAAK,CACd,oDAAoD,CACpD,CAAC;SACF;QACD,OAAO,MAAM,CAAC;IACf,CAAC;IAED,IAAI,WAAW;QACd,OAAO,CACN,IAAI,CAAC,QAAQ,CAAC,CAAC,WAAW;YAC1B,CAAC,IAAI,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CACvC,CAAC;IACH,CAAC;IAED,IAAI,WAAW,CAAC,CAAS;QACxB,IAAI,IAAI,CAAC,QAAQ,CAAC,EAAE;YACnB,IAAI,CAAC,QAAQ,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC;SAC/B;IACF,CAAC;IAED,IAAI,QAAQ;QACX,OAAO,CACN,IAAI,CAAC,QAAQ,CAAC,CAAC,QAAQ;YACvB,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAC9C,CAAC;IACH,CAAC;IAED,IAAI,QAAQ,CAAC,CAAS;QACrB,IAAI,IAAI,CAAC,QAAQ,CAAC,EAAE;YACnB,IAAI,CAAC,QAAQ,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC;SAC5B;IACF,CAAC;CACD;AAlLD,sBAkLC"}

46
node_modules/agent-base/package.json generated vendored Normal file
View File

@ -0,0 +1,46 @@
{
"name": "agent-base",
"version": "7.1.4",
"description": "Turn a function into an `http.Agent` instance",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"repository": {
"type": "git",
"url": "https://github.com/TooTallNate/proxy-agents.git",
"directory": "packages/agent-base"
},
"keywords": [
"http",
"agent",
"base",
"barebones",
"https"
],
"author": "Nathan Rajlich <nathan@tootallnate.net> (http://n8.io/)",
"license": "MIT",
"devDependencies": {
"@types/debug": "^4.1.7",
"@types/jest": "^29.5.1",
"@types/node": "^14.18.45",
"@types/semver": "^7.3.13",
"@types/ws": "^6.0.4",
"async-listen": "^3.0.0",
"jest": "^29.5.0",
"ts-jest": "^29.1.0",
"typescript": "^5.0.4",
"ws": "^5.2.4",
"tsconfig": "0.0.0"
},
"engines": {
"node": ">= 14"
},
"scripts": {
"build": "tsc",
"test": "jest --env node --verbose --bail",
"lint": "eslint . --ext .ts",
"pack": "node ../../scripts/pack.mjs"
}
}

21
node_modules/base64-js/LICENSE generated vendored Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014 Jameson Little
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

34
node_modules/base64-js/README.md generated vendored Normal file
View File

@ -0,0 +1,34 @@
base64-js
=========
`base64-js` does basic base64 encoding/decoding in pure JS.
[![build status](https://secure.travis-ci.org/beatgammit/base64-js.png)](http://travis-ci.org/beatgammit/base64-js)
Many browsers already have base64 encoding/decoding functionality, but it is for text data, not all-purpose binary data.
Sometimes encoding/decoding binary data in the browser is useful, and that is what this module does.
## install
With [npm](https://npmjs.org) do:
`npm install base64-js` and `var base64js = require('base64-js')`
For use in web browsers do:
`<script src="base64js.min.js"></script>`
[Get supported base64-js with the Tidelift Subscription](https://tidelift.com/subscription/pkg/npm-base64-js?utm_source=npm-base64-js&utm_medium=referral&utm_campaign=readme)
## methods
`base64js` has three exposed functions, `byteLength`, `toByteArray` and `fromByteArray`, which both take a single argument.
* `byteLength` - Takes a base64 string and returns length of byte array
* `toByteArray` - Takes a base64 string and returns a byte array
* `fromByteArray` - Takes a byte array and returns a base64 string
## license
MIT

1
node_modules/base64-js/base64js.min.js generated vendored Normal file
View File

@ -0,0 +1 @@
(function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"==typeof window?"undefined"==typeof global?"undefined"==typeof self?this:self:global:window,b.base64js=a()}})(function(){return function(){function b(d,e,g){function a(j,i){if(!e[j]){if(!d[j]){var f="function"==typeof require&&require;if(!i&&f)return f(j,!0);if(h)return h(j,!0);var c=new Error("Cannot find module '"+j+"'");throw c.code="MODULE_NOT_FOUND",c}var k=e[j]={exports:{}};d[j][0].call(k.exports,function(b){var c=d[j][1][b];return a(c||b)},k,k.exports,b,d,e,g)}return e[j].exports}for(var h="function"==typeof require&&require,c=0;c<g.length;c++)a(g[c]);return a}return b}()({"/":[function(a,b,c){'use strict';function d(a){var b=a.length;if(0<b%4)throw new Error("Invalid string. Length must be a multiple of 4");var c=a.indexOf("=");-1===c&&(c=b);var d=c===b?0:4-c%4;return[c,d]}function e(a,b,c){return 3*(b+c)/4-c}function f(a){var b,c,f=d(a),g=f[0],h=f[1],j=new m(e(a,g,h)),k=0,n=0<h?g-4:g;for(c=0;c<n;c+=4)b=l[a.charCodeAt(c)]<<18|l[a.charCodeAt(c+1)]<<12|l[a.charCodeAt(c+2)]<<6|l[a.charCodeAt(c+3)],j[k++]=255&b>>16,j[k++]=255&b>>8,j[k++]=255&b;return 2===h&&(b=l[a.charCodeAt(c)]<<2|l[a.charCodeAt(c+1)]>>4,j[k++]=255&b),1===h&&(b=l[a.charCodeAt(c)]<<10|l[a.charCodeAt(c+1)]<<4|l[a.charCodeAt(c+2)]>>2,j[k++]=255&b>>8,j[k++]=255&b),j}function g(a){return k[63&a>>18]+k[63&a>>12]+k[63&a>>6]+k[63&a]}function h(a,b,c){for(var d,e=[],f=b;f<c;f+=3)d=(16711680&a[f]<<16)+(65280&a[f+1]<<8)+(255&a[f+2]),e.push(g(d));return e.join("")}function j(a){for(var b,c=a.length,d=c%3,e=[],f=16383,g=0,j=c-d;g<j;g+=f)e.push(h(a,g,g+f>j?j:g+f));return 1===d?(b=a[c-1],e.push(k[b>>2]+k[63&b<<4]+"==")):2===d&&(b=(a[c-2]<<8)+a[c-1],e.push(k[b>>10]+k[63&b>>4]+k[63&b<<2]+"=")),e.join("")}c.byteLength=function(a){var b=d(a),c=b[0],e=b[1];return 3*(c+e)/4-e},c.toByteArray=f,c.fromByteArray=j;for(var k=[],l=[],m="undefined"==typeof Uint8Array?Array:Uint8Array,n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",o=0,p=n.length;o<p;++o)k[o]=n[o],l[n.charCodeAt(o)]=o;l[45]=62,l[95]=63},{}]},{},[])("/")});

3
node_modules/base64-js/index.d.ts generated vendored Normal file
View File

@ -0,0 +1,3 @@
export function byteLength(b64: string): number;
export function toByteArray(b64: string): Uint8Array;
export function fromByteArray(uint8: Uint8Array): string;

150
node_modules/base64-js/index.js generated vendored Normal file
View File

@ -0,0 +1,150 @@
'use strict'
exports.byteLength = byteLength
exports.toByteArray = toByteArray
exports.fromByteArray = fromByteArray
var lookup = []
var revLookup = []
var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array
var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
for (var i = 0, len = code.length; i < len; ++i) {
lookup[i] = code[i]
revLookup[code.charCodeAt(i)] = i
}
// Support decoding URL-safe base64 strings, as Node.js does.
// See: https://en.wikipedia.org/wiki/Base64#URL_applications
revLookup['-'.charCodeAt(0)] = 62
revLookup['_'.charCodeAt(0)] = 63
function getLens (b64) {
var len = b64.length
if (len % 4 > 0) {
throw new Error('Invalid string. Length must be a multiple of 4')
}
// Trim off extra bytes after placeholder bytes are found
// See: https://github.com/beatgammit/base64-js/issues/42
var validLen = b64.indexOf('=')
if (validLen === -1) validLen = len
var placeHoldersLen = validLen === len
? 0
: 4 - (validLen % 4)
return [validLen, placeHoldersLen]
}
// base64 is 4/3 + up to two characters of the original data
function byteLength (b64) {
var lens = getLens(b64)
var validLen = lens[0]
var placeHoldersLen = lens[1]
return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen
}
function _byteLength (b64, validLen, placeHoldersLen) {
return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen
}
function toByteArray (b64) {
var tmp
var lens = getLens(b64)
var validLen = lens[0]
var placeHoldersLen = lens[1]
var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen))
var curByte = 0
// if there are placeholders, only get up to the last complete 4 chars
var len = placeHoldersLen > 0
? validLen - 4
: validLen
var i
for (i = 0; i < len; i += 4) {
tmp =
(revLookup[b64.charCodeAt(i)] << 18) |
(revLookup[b64.charCodeAt(i + 1)] << 12) |
(revLookup[b64.charCodeAt(i + 2)] << 6) |
revLookup[b64.charCodeAt(i + 3)]
arr[curByte++] = (tmp >> 16) & 0xFF
arr[curByte++] = (tmp >> 8) & 0xFF
arr[curByte++] = tmp & 0xFF
}
if (placeHoldersLen === 2) {
tmp =
(revLookup[b64.charCodeAt(i)] << 2) |
(revLookup[b64.charCodeAt(i + 1)] >> 4)
arr[curByte++] = tmp & 0xFF
}
if (placeHoldersLen === 1) {
tmp =
(revLookup[b64.charCodeAt(i)] << 10) |
(revLookup[b64.charCodeAt(i + 1)] << 4) |
(revLookup[b64.charCodeAt(i + 2)] >> 2)
arr[curByte++] = (tmp >> 8) & 0xFF
arr[curByte++] = tmp & 0xFF
}
return arr
}
function tripletToBase64 (num) {
return lookup[num >> 18 & 0x3F] +
lookup[num >> 12 & 0x3F] +
lookup[num >> 6 & 0x3F] +
lookup[num & 0x3F]
}
function encodeChunk (uint8, start, end) {
var tmp
var output = []
for (var i = start; i < end; i += 3) {
tmp =
((uint8[i] << 16) & 0xFF0000) +
((uint8[i + 1] << 8) & 0xFF00) +
(uint8[i + 2] & 0xFF)
output.push(tripletToBase64(tmp))
}
return output.join('')
}
function fromByteArray (uint8) {
var tmp
var len = uint8.length
var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes
var parts = []
var maxChunkLength = 16383 // must be multiple of 3
// go through the array every three bytes, we'll deal with trailing stuff later
for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)))
}
// pad the end with zeros, but make sure to not forget the extra bytes
if (extraBytes === 1) {
tmp = uint8[len - 1]
parts.push(
lookup[tmp >> 2] +
lookup[(tmp << 4) & 0x3F] +
'=='
)
} else if (extraBytes === 2) {
tmp = (uint8[len - 2] << 8) + uint8[len - 1]
parts.push(
lookup[tmp >> 10] +
lookup[(tmp >> 4) & 0x3F] +
lookup[(tmp << 2) & 0x3F] +
'='
)
}
return parts.join('')
}

47
node_modules/base64-js/package.json generated vendored Normal file
View File

@ -0,0 +1,47 @@
{
"name": "base64-js",
"description": "Base64 encoding/decoding in pure JS",
"version": "1.5.1",
"author": "T. Jameson Little <t.jameson.little@gmail.com>",
"typings": "index.d.ts",
"bugs": {
"url": "https://github.com/beatgammit/base64-js/issues"
},
"devDependencies": {
"babel-minify": "^0.5.1",
"benchmark": "^2.1.4",
"browserify": "^16.3.0",
"standard": "*",
"tape": "4.x"
},
"homepage": "https://github.com/beatgammit/base64-js",
"keywords": [
"base64"
],
"license": "MIT",
"main": "index.js",
"repository": {
"type": "git",
"url": "git://github.com/beatgammit/base64-js.git"
},
"scripts": {
"build": "browserify -s base64js -r ./ | minify > base64js.min.js",
"lint": "standard",
"test": "npm run lint && npm run unit",
"unit": "tape test/*.js"
},
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
}

27
node_modules/bcryptjs/LICENSE generated vendored Normal file
View File

@ -0,0 +1,27 @@
bcrypt.js
---------
Copyright (c) 2012 Nevins Bartolomeo <nevins.bartolomeo@gmail.com>
Copyright (c) 2012 Shane Girish <shaneGirish@gmail.com>
Copyright (c) 2025 Daniel Wirtz <dcode@dcode.io>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

201
node_modules/bcryptjs/README.md generated vendored Normal file
View File

@ -0,0 +1,201 @@
# bcrypt.js
Optimized bcrypt in JavaScript with zero dependencies, with TypeScript support. Compatible to the C++
[bcrypt](https://npmjs.org/package/bcrypt) binding on Node.js and also working in the browser.
[![Build Status](https://img.shields.io/github/actions/workflow/status/dcodeIO/bcrypt.js/test.yml?branch=main&label=test&logo=github)](https://github.com/dcodeIO/bcrypt.js/actions/workflows/test.yml) [![Publish Status](https://img.shields.io/github/actions/workflow/status/dcodeIO/bcrypt.js/publish.yml?branch=main&label=publish&logo=github)](https://github.com/dcodeIO/bcrypt.js/actions/workflows/publish.yml) [![npm](https://img.shields.io/npm/v/bcryptjs.svg?label=npm&color=007acc&logo=npm)](https://www.npmjs.com/package/bcryptjs)
## Security considerations
Besides incorporating a salt to protect against rainbow table attacks, bcrypt is an adaptive function: over time, the
iteration count can be increased to make it slower, so it remains resistant to brute-force search attacks even with
increasing computation power. ([see](http://en.wikipedia.org/wiki/Bcrypt))
While bcrypt.js is compatible to the C++ bcrypt binding, it is written in pure JavaScript and thus slower ([about 30%](https://github.com/dcodeIO/bcrypt.js/wiki/Benchmark)), effectively reducing the number of iterations that can be
processed in an equal time span.
The maximum input length is 72 bytes (note that UTF-8 encoded characters use up to 4 bytes) and the length of generated
hashes is 60 characters. Note that maximum input length is not implicitly checked by the library for compatibility with
the C++ binding on Node.js, but should be checked with `bcrypt.truncates(password)` where necessary.
## Usage
The package exports an ECMAScript module with an UMD fallback.
```
$> npm install bcryptjs
```
```ts
import bcrypt from "bcryptjs";
```
### Usage with a CDN
- From GitHub via [jsDelivr](https://www.jsdelivr.com):<br />
`https://cdn.jsdelivr.net/gh/dcodeIO/bcrypt.js@TAG/index.js` (ESM)
- From npm via [jsDelivr](https://www.jsdelivr.com):<br />
`https://cdn.jsdelivr.net/npm/bcryptjs@VERSION/index.js` (ESM)<br />
`https://cdn.jsdelivr.net/npm/bcryptjs@VERSION/umd/index.js` (UMD)
- From npm via [unpkg](https://unpkg.com):<br />
`https://unpkg.com/bcryptjs@VERSION/index.js` (ESM)<br />
`https://unpkg.com/bcryptjs@VERSION/umd/index.js` (UMD)
Replace `TAG` respectively `VERSION` with a [specific version](https://github.com/dcodeIO/bcrypt.js/releases) or omit it (not recommended in production) to use latest.
When using the ESM variant in a browser, the `crypto` import needs to be stubbed out, for example using an [import map](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap). Bundlers should omit it automatically.
### Usage - Sync
To hash a password:
```ts
const salt = bcrypt.genSaltSync(10);
const hash = bcrypt.hashSync("B4c0/\/", salt);
// Store hash in your password DB
```
To check a password:
```ts
// Load hash from your password DB
bcrypt.compareSync("B4c0/\/", hash); // true
bcrypt.compareSync("not_bacon", hash); // false
```
Auto-gen a salt and hash:
```ts
const hash = bcrypt.hashSync("bacon", 10);
```
### Usage - Async
To hash a password:
```ts
const salt = await bcrypt.genSalt(10);
const hash = await bcrypt.hash("B4c0/\/", salt);
// Store hash in your password DB
```
```ts
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash("B4c0/\/", salt, function (err, hash) {
// Store hash in your password DB
});
});
```
To check a password:
```ts
// Load hash from your password DB
await bcrypt.compare("B4c0/\/", hash); // true
await bcrypt.compare("not_bacon", hash); // false
```
```ts
// Load hash from your password DB
bcrypt.compare("B4c0/\/", hash, (err, res) => {
// res === true
});
bcrypt.compare("not_bacon", hash, (err, res) => {
// res === false
});
```
Auto-gen a salt and hash:
```ts
await bcrypt.hash("B4c0/\/", 10);
// Store hash in your password DB
```
```ts
bcrypt.hash("B4c0/\/", 10, (err, hash) => {
// Store hash in your password DB
});
```
**Note:** Under the hood, asynchronous APIs split an operation into small chunks. After the completion of a chunk, the execution of the next chunk is placed on the back of the [JS event queue](https://developer.mozilla.org/en/docs/Web/JavaScript/EventLoop), efficiently yielding for other computation to execute.
### Usage - Command Line
```
Usage: bcrypt <input> [rounds|salt]
```
## API
### Callback types
- **Callback<`T`>**: `(err: Error | null, result?: T) => void`<br />
Called with an error on failure or a value of type `T` upon success.
- **ProgressCallback**: `(percentage: number) => void`<br />
Called with the percentage of rounds completed (0.0 - 1.0), maximally once per `MAX_EXECUTION_TIME = 100` ms.
- **RandomFallback**: `(length: number) => number[]`<br />
Called to obtain random bytes when both [Web Crypto API](http://www.w3.org/TR/WebCryptoAPI/) and Node.js
[crypto](http://nodejs.org/api/crypto.html) are not available.
### Functions
- bcrypt.**genSaltSync**(rounds?: `number`): `string`<br />
Synchronously generates a salt. Number of rounds defaults to 10 when omitted.
- bcrypt.**genSalt**(rounds?: `number`): `Promise<string>`<br />
Asynchronously generates a salt. Number of rounds defaults to 10 when omitted.
- bcrypt.**genSalt**([rounds: `number`, ]callback: `Callback<string>`): `void`<br />
Asynchronously generates a salt. Number of rounds defaults to 10 when omitted.
- bcrypt.**truncates**(password: `string`): `boolean`<br />
Tests if a password will be truncated when hashed, that is its length is greater than 72 bytes when converted to UTF-8.
- bcrypt.**hashSync**(password: `string`, salt?: `number | string`): `string`
Synchronously generates a hash for the given password. Number of rounds defaults to 10 when omitted.
- bcrypt.**hash**(password: `string`, salt: `number | string`): `Promise<string>`<br />
Asynchronously generates a hash for the given password.
- bcrypt.**hash**(password: `string`, salt: `number | string`, callback: `Callback<string>`, progressCallback?: `ProgressCallback`): `void`<br />
Asynchronously generates a hash for the given password.
- bcrypt.**compareSync**(password: `string`, hash: `string`): `boolean`<br />
Synchronously tests a password against a hash.
- bcrypt.**compare**(password: `string`, hash: `string`): `Promise<boolean>`<br />
Asynchronously compares a password against a hash.
- bcrypt.**compare**(password: `string`, hash: `string`, callback: `Callback<boolean>`, progressCallback?: `ProgressCallback`)<br />
Asynchronously compares a password against a hash.
- bcrypt.**getRounds**(hash: `string`): `number`<br />
Gets the number of rounds used to encrypt the specified hash.
- bcrypt.**getSalt**(hash: `string`): `string`<br />
Gets the salt portion from a hash. Does not validate the hash.
- bcrypt.**setRandomFallback**(random: `RandomFallback`): `void`<br />
Sets the pseudo random number generator to use as a fallback if neither [Web Crypto API](http://www.w3.org/TR/WebCryptoAPI/) nor Node.js [crypto](http://nodejs.org/api/crypto.html) are available. Please note: It is highly important that the PRNG used is cryptographically secure and that it is seeded properly!
## Building
Building the UMD fallback:
```
$> npm run build
```
Running the [tests](./tests):
```
$> npm test
```
## Credits
Based on work started by Shane Girish at [bcrypt-nodejs](https://github.com/shaneGirish/bcrypt-nodejs), which is itself
based on [javascript-bcrypt](http://code.google.com/p/javascript-bcrypt/) (New BSD-licensed).

23
node_modules/bcryptjs/bin/bcrypt generated vendored Normal file
View File

@ -0,0 +1,23 @@
#!/usr/bin/env node
import path from "node:path";
import bcrypt from "../index.js";
if (process.argv.length < 3) {
console.log(
"Usage: " + path.basename(process.argv[1]) + " <input> [rounds|salt]",
);
process.exit(1);
} else {
var salt;
if (process.argv.length > 3) {
salt = process.argv[3];
var rounds = parseInt(salt, 10);
if (rounds == salt) {
salt = bcrypt.genSaltSync(rounds);
}
} else {
salt = bcrypt.genSaltSync();
}
console.log(bcrypt.hashSync(process.argv[2], salt));
}

3
node_modules/bcryptjs/index.d.ts generated vendored Normal file
View File

@ -0,0 +1,3 @@
import * as bcrypt from "./types.js";
export * from "./types.js";
export default bcrypt;

1159
node_modules/bcryptjs/index.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

76
node_modules/bcryptjs/package.json generated vendored Normal file
View File

@ -0,0 +1,76 @@
{
"name": "bcryptjs",
"description": "Optimized bcrypt in plain JavaScript with zero dependencies, with TypeScript support. Compatible to 'bcrypt'.",
"version": "3.0.3",
"author": "Daniel Wirtz <dcode@dcode.io>",
"contributors": [
"Shane Girish <shaneGirish@gmail.com> (https://github.com/shaneGirish)",
"Alex Murray <> (https://github.com/alexmurray)",
"Nicolas Pelletier <> (https://github.com/NicolasPelletier)",
"Josh Rogers <> (https://github.com/geekymole)",
"Noah Isaacson <noah@nisaacson.com> (https://github.com/nisaacson)"
],
"repository": {
"type": "url",
"url": "https://github.com/dcodeIO/bcrypt.js.git"
},
"bugs": {
"url": "https://github.com/dcodeIO/bcrypt.js/issues"
},
"keywords": [
"bcrypt",
"password",
"auth",
"authentication",
"encryption",
"crypt",
"crypto"
],
"type": "module",
"main": "umd/index.js",
"types": "umd/index.d.ts",
"exports": {
".": {
"import": {
"types": "./index.d.ts",
"default": "./index.js"
},
"require": {
"types": "./umd/index.d.ts",
"default": "./umd/index.js"
}
}
},
"bin": {
"bcrypt": "bin/bcrypt"
},
"license": "BSD-3-Clause",
"scripts": {
"build": "node scripts/build.js",
"lint": "prettier --check .",
"format": "prettier --write .",
"test": "npm run test:unit && npm run test:typescript",
"test:unit": "node tests",
"test:typescript": "tsc --project tests/typescript/tsconfig.esnext.json && tsc --project tests/typescript/tsconfig.nodenext.json && tsc --project tests/typescript/tsconfig.commonjs.json && tsc --project tests/typescript/tsconfig.global.json"
},
"files": [
"index.js",
"index.d.ts",
"types.d.ts",
"umd/index.js",
"umd/index.d.ts",
"umd/types.d.ts",
"umd/package.json",
"LICENSE",
"README.md"
],
"browser": {
"crypto": false
},
"devDependencies": {
"bcrypt": "^5.1.1",
"esm2umd": "^0.3.1",
"prettier": "^3.5.0",
"typescript": "^5.7.3"
}
}

157
node_modules/bcryptjs/types.d.ts generated vendored Normal file
View File

@ -0,0 +1,157 @@
// Originally imported from https://github.com/DefinitelyTyped/DefinitelyTyped/blob/8b36dbdf95b624b8a7cd7f8416f06c15d274f9e6/types/bcryptjs/index.d.ts
// MIT license.
/** Called with an error on failure or a value of type `T` upon success. */
type Callback<T> = (err: Error | null, result?: T) => void;
/** Called with the percentage of rounds completed (0.0 - 1.0), maximally once per `MAX_EXECUTION_TIME = 100` ms. */
type ProgressCallback = (percentage: number) => void;
/** Called to obtain random bytes when both Web Crypto API and Node.js crypto are not available. */
type RandomFallback = (length: number) => number[];
/**
* Sets the pseudo random number generator to use as a fallback if neither node's crypto module nor the Web Crypto API is available.
* Please note: It is highly important that the PRNG used is cryptographically secure and that it is seeded properly!
* @param random Function taking the number of bytes to generate as its sole argument, returning the corresponding array of cryptographically secure random byte values.
*/
export declare function setRandomFallback(random: RandomFallback): void;
/**
* Synchronously generates a salt.
* @param rounds Number of rounds to use, defaults to 10 if omitted
* @return Resulting salt
* @throws If a random fallback is required but not set
*/
export declare function genSaltSync(rounds?: number): string;
/**
* Asynchronously generates a salt.
* @param rounds Number of rounds to use, defaults to 10 if omitted
* @return Promise with resulting salt, if callback has been omitted
*/
export declare function genSalt(rounds?: number): Promise<string>;
/**
* Asynchronously generates a salt.
* @param callback Callback receiving the error, if any, and the resulting salt
*/
export declare function genSalt(callback: Callback<string>): void;
/**
* Asynchronously generates a salt.
* @param rounds Number of rounds to use, defaults to 10 if omitted
* @param callback Callback receiving the error, if any, and the resulting salt
*/
export declare function genSalt(
rounds: number,
callback: Callback<string>,
): void;
/**
* Synchronously generates a hash for the given password.
* @param password Password to hash
* @param salt Salt length to generate or salt to use, default to 10
* @return Resulting hash
*/
export declare function hashSync(
password: string,
salt?: number | string,
): string;
/**
* Asynchronously generates a hash for the given password.
* @param password Password to hash
* @param salt Salt length to generate or salt to use
* @return Promise with resulting hash, if callback has been omitted
*/
export declare function hash(
password: string,
salt: number | string,
): Promise<string>;
/**
* Asynchronously generates a hash for the given password.
* @param password Password to hash
* @param salt Salt length to generate or salt to use
* @param callback Callback receiving the error, if any, and the resulting hash
* @param progressCallback Callback successively called with the percentage of rounds completed (0.0 - 1.0), maximally once per MAX_EXECUTION_TIME = 100 ms.
*/
export declare function hash(
password: string,
salt: number | string,
callback?: Callback<string>,
progressCallback?: ProgressCallback,
): void;
/**
* Synchronously tests a password against a hash.
* @param password Password to test
* @param hash Hash to test against
* @return true if matching, otherwise false
*/
export declare function compareSync(password: string, hash: string): boolean;
/**
* Asynchronously tests a password against a hash.
* @param password Password to test
* @param hash Hash to test against
* @return Promise, if callback has been omitted
*/
export declare function compare(
password: string,
hash: string,
): Promise<boolean>;
/**
* Asynchronously tests a password against a hash.
* @param password Password to test
* @param hash Hash to test against
* @param callback Callback receiving the error, if any, otherwise the result
* @param progressCallback Callback successively called with the percentage of rounds completed (0.0 - 1.0), maximally once per MAX_EXECUTION_TIME = 100 ms.
*/
export declare function compare(
password: string,
hash: string,
callback?: Callback<boolean>,
progressCallback?: ProgressCallback,
): void;
/**
* Gets the number of rounds used to encrypt the specified hash.
* @param hash Hash to extract the used number of rounds from
* @return Number of rounds used
*/
export declare function getRounds(hash: string): number;
/**
* Gets the salt portion from a hash. Does not validate the hash.
* @param hash Hash to extract the salt from
* @return Extracted salt part
*/
export declare function getSalt(hash: string): string;
/**
* Tests if a password will be truncated when hashed, that is its length is
* greater than 72 bytes when converted to UTF-8.
* @param password The password to test
* @returns `true` if truncated, otherwise `false`
*/
export declare function truncates(password: string): boolean;
/**
* Encodes a byte array to base64 with up to len bytes of input, using the custom bcrypt alphabet.
* @function
* @param b Byte array
* @param len Maximum input length
*/
export declare function encodeBase64(
b: Readonly<ArrayLike<number>>,
len: number,
): string;
/**
* Decodes a base64 encoded string to up to len bytes of output, using the custom bcrypt alphabet.
* @function
* @param s String to decode
* @param len Maximum output length
*/
export declare function decodeBase64(s: string, len: number): number[];

3
node_modules/bcryptjs/umd/index.d.ts generated vendored Normal file
View File

@ -0,0 +1,3 @@
import * as bcrypt from "./types.js";
export = bcrypt;
export as namespace bcrypt;

1220
node_modules/bcryptjs/umd/index.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

3
node_modules/bcryptjs/umd/package.json generated vendored Normal file
View File

@ -0,0 +1,3 @@
{
"type": "commonjs"
}

157
node_modules/bcryptjs/umd/types.d.ts generated vendored Normal file
View File

@ -0,0 +1,157 @@
// Originally imported from https://github.com/DefinitelyTyped/DefinitelyTyped/blob/8b36dbdf95b624b8a7cd7f8416f06c15d274f9e6/types/bcryptjs/index.d.ts
// MIT license.
/** Called with an error on failure or a value of type `T` upon success. */
type Callback<T> = (err: Error | null, result?: T) => void;
/** Called with the percentage of rounds completed (0.0 - 1.0), maximally once per `MAX_EXECUTION_TIME = 100` ms. */
type ProgressCallback = (percentage: number) => void;
/** Called to obtain random bytes when both Web Crypto API and Node.js crypto are not available. */
type RandomFallback = (length: number) => number[];
/**
* Sets the pseudo random number generator to use as a fallback if neither node's crypto module nor the Web Crypto API is available.
* Please note: It is highly important that the PRNG used is cryptographically secure and that it is seeded properly!
* @param random Function taking the number of bytes to generate as its sole argument, returning the corresponding array of cryptographically secure random byte values.
*/
export declare function setRandomFallback(random: RandomFallback): void;
/**
* Synchronously generates a salt.
* @param rounds Number of rounds to use, defaults to 10 if omitted
* @return Resulting salt
* @throws If a random fallback is required but not set
*/
export declare function genSaltSync(rounds?: number): string;
/**
* Asynchronously generates a salt.
* @param rounds Number of rounds to use, defaults to 10 if omitted
* @return Promise with resulting salt, if callback has been omitted
*/
export declare function genSalt(rounds?: number): Promise<string>;
/**
* Asynchronously generates a salt.
* @param callback Callback receiving the error, if any, and the resulting salt
*/
export declare function genSalt(callback: Callback<string>): void;
/**
* Asynchronously generates a salt.
* @param rounds Number of rounds to use, defaults to 10 if omitted
* @param callback Callback receiving the error, if any, and the resulting salt
*/
export declare function genSalt(
rounds: number,
callback: Callback<string>,
): void;
/**
* Synchronously generates a hash for the given password.
* @param password Password to hash
* @param salt Salt length to generate or salt to use, default to 10
* @return Resulting hash
*/
export declare function hashSync(
password: string,
salt?: number | string,
): string;
/**
* Asynchronously generates a hash for the given password.
* @param password Password to hash
* @param salt Salt length to generate or salt to use
* @return Promise with resulting hash, if callback has been omitted
*/
export declare function hash(
password: string,
salt: number | string,
): Promise<string>;
/**
* Asynchronously generates a hash for the given password.
* @param password Password to hash
* @param salt Salt length to generate or salt to use
* @param callback Callback receiving the error, if any, and the resulting hash
* @param progressCallback Callback successively called with the percentage of rounds completed (0.0 - 1.0), maximally once per MAX_EXECUTION_TIME = 100 ms.
*/
export declare function hash(
password: string,
salt: number | string,
callback?: Callback<string>,
progressCallback?: ProgressCallback,
): void;
/**
* Synchronously tests a password against a hash.
* @param password Password to test
* @param hash Hash to test against
* @return true if matching, otherwise false
*/
export declare function compareSync(password: string, hash: string): boolean;
/**
* Asynchronously tests a password against a hash.
* @param password Password to test
* @param hash Hash to test against
* @return Promise, if callback has been omitted
*/
export declare function compare(
password: string,
hash: string,
): Promise<boolean>;
/**
* Asynchronously tests a password against a hash.
* @param password Password to test
* @param hash Hash to test against
* @param callback Callback receiving the error, if any, otherwise the result
* @param progressCallback Callback successively called with the percentage of rounds completed (0.0 - 1.0), maximally once per MAX_EXECUTION_TIME = 100 ms.
*/
export declare function compare(
password: string,
hash: string,
callback?: Callback<boolean>,
progressCallback?: ProgressCallback,
): void;
/**
* Gets the number of rounds used to encrypt the specified hash.
* @param hash Hash to extract the used number of rounds from
* @return Number of rounds used
*/
export declare function getRounds(hash: string): number;
/**
* Gets the salt portion from a hash. Does not validate the hash.
* @param hash Hash to extract the salt from
* @return Extracted salt part
*/
export declare function getSalt(hash: string): string;
/**
* Tests if a password will be truncated when hashed, that is its length is
* greater than 72 bytes when converted to UTF-8.
* @param password The password to test
* @returns `true` if truncated, otherwise `false`
*/
export declare function truncates(password: string): boolean;
/**
* Encodes a byte array to base64 with up to len bytes of input, using the custom bcrypt alphabet.
* @function
* @param b Byte array
* @param len Maximum input length
*/
export declare function encodeBase64(
b: Readonly<ArrayLike<number>>,
len: number,
): string;
/**
* Decodes a base64 encoded string to up to len bytes of output, using the custom bcrypt alphabet.
* @function
* @param s String to decode
* @param len Maximum output length
*/
export declare function decodeBase64(s: string, len: number): number[];

381
node_modules/bignumber.js/CHANGELOG.md generated vendored Normal file
View File

@ -0,0 +1,381 @@
#### 9.3.1
* 11/07/25
* [BUGFIX] #388 `toPrecision` fix.
#### 9.3.0
* 19/04/25
* Refactor type declarations:
* Rename *bignumber.d.ts* to *types.d.ts*.
* Rename *bignumber.d.cts* to *bignumber.d.ts*.
* Add `export as namespace` to *bignumber.d.ts*.
* Remove subpath exports from *package.json*.
* Refactor named export from *bignumber.d.mts*.
* #383 Remove `?` from static `BigNumber` and `default` properties.
* Add blank lines after titles in *CHANGELOG.md*.
#### 9.2.1
* 08/04/25
* #371 #382 Add `BigNumber` as named export.
#### 9.2.0
* 03/04/25
* #355 Support `BigInt` argument.
* #371 Provide separate type definitions for CommonJS and ES modules.
* #374 Correct `comparedTo` return type.
#### 9.1.2
* 28/08/23
* #354 Amend `round` to avoid bug in v8 Maglev compiler.
* [BUGFIX] #344 `minimum(0, -0)` should be `-0`.
#### 9.1.1
* 04/12/22
* #338 [BUGFIX] `exponentiatedBy`: ensure `0**-n === Infinity` for very large `n`.
#### 9.1.0
* 08/08/22
* #329 Remove `import` example.
* #277 Resolve lint warnings and add number `toString` note.
* Correct `decimalPlaces()` return type in *bignumber.d.ts*.
* Add ES module global `crypto` example.
* #322 Add `exports` field to *package.json*.
* #251 (#308) Amend *bignumber.d.ts* to allow instantiating a BigNumber without `new`.
#### 9.0.2
* 12/12/21
* #250 [BUGFIX] Allow use of user-defined alphabet for base 10.
* #295 Remove *bignumber.min.js* and amend *README.md*.
* Update *.travis.yml* and *LICENCE.md*.
#### 9.0.1
* 28/09/20
* [BUGFIX] #276 Correct `sqrt` initial estimate.
* Update *.travis.yml*, *LICENCE.md* and *README.md*.
#### 9.0.0
* 27/05/2019
* For compatibility with legacy browsers, remove `Symbol` references.
#### 8.1.1
* 24/02/2019
* [BUGFIX] #222 Restore missing `var` to `export BigNumber`.
* Allow any key in BigNumber.Instance in *bignumber.d.ts*.
#### 8.1.0
* 23/02/2019
* [NEW FEATURE] #220 Create a BigNumber using `{s, e, c}`.
* [NEW FEATURE] `isBigNumber`: if `BigNumber.DEBUG` is `true`, also check that the BigNumber instance is well-formed.
* Remove `instanceof` checks; just use `_isBigNumber` to identify a BigNumber instance.
* Add `_isBigNumber` to prototype in *bignumber.mjs*.
* Add tests for BigNumber creation from object.
* Update *API.html*.
#### 8.0.2
* 13/01/2019
* #209 `toPrecision` without argument should follow `toString`.
* Improve *Use* section of *README*.
* Optimise `toString(10)`.
* Add verson number to API doc.
#### 8.0.1
* 01/11/2018
* Rest parameter must be array type in *bignumber.d.ts*.
#### 8.0.0
* 01/11/2018
* [NEW FEATURE] Add `BigNumber.sum` method.
* [NEW FEATURE]`toFormat`: add `prefix` and `suffix` options.
* [NEW FEATURE] #178 Pass custom formatting to `toFormat`.
* [BREAKING CHANGE] #184 `toFraction`: return array of BigNumbers not strings.
* [NEW FEATURE] #185 Enable overwrite of `valueOf` to prevent accidental addition to string.
* #183 Add Node.js `crypto` requirement to documentation.
* [BREAKING CHANGE] #198 Disallow signs and whitespace in custom alphabet.
* [NEW FEATURE] #188 Implement `util.inspect.custom` for Node.js REPL.
* #170 Make `isBigNumber` a type guard in *bignumber.d.ts*.
* [BREAKING CHANGE] `BigNumber.min` and `BigNumber.max`: don't accept an array.
* Update *.travis.yml*.
* Remove *bower.json*.
#### 7.2.1
* 24/05/2018
* Add `browser` field to *package.json*.
#### 7.2.0
* 22/05/2018
* #166 Correct *.mjs* file. Remove extension from `main` field in *package.json*.
#### 7.1.0
* 18/05/2018
* Add `module` field to *package.json* for *bignumber.mjs*.
#### 7.0.2
* 17/05/2018
* #165 Bugfix: upper-case letters for bases 11-36 in a custom alphabet.
* Add note to *README* regarding creating BigNumbers from Number values.
#### 7.0.1
* 26/04/2018
* #158 Fix global object variable name typo.
#### 7.0.0
* 26/04/2018
* #143 Remove global BigNumber from typings.
* #144 Enable compatibility with `Object.freeze(Object.prototype)`.
* #148 #123 #11 Only throw on a number primitive with more than 15 significant digits if `BigNumber.DEBUG` is `true`.
* Only throw on an invalid BigNumber value if `BigNumber.DEBUG` is `true`. Return BigNumber `NaN` instead.
* #154 `exponentiatedBy`: allow BigNumber exponent.
* #156 Prevent Content Security Policy *unsafe-eval* issue.
* `toFraction`: allow `Infinity` maximum denominator.
* Comment-out some excess tests to reduce test time.
* Amend indentation and other spacing.
#### 6.0.0
* 26/01/2018
* #137 Implement `APLHABET` configuration option.
* Remove `ERRORS` configuration option.
* Remove `toDigits` method; extend `precision` method accordingly.
* Remove s`round` method; extend `decimalPlaces` method accordingly.
* Remove methods: `ceil`, `floor`, and `truncated`.
* Remove method aliases: `add`, `cmp`, `isInt`, `isNeg`, `trunc`, `mul`, `neg` and `sub`.
* Rename methods: `shift` to `shiftedBy`, `another` to `clone`, `toPower` to `exponentiatedBy`, and `equals` to `isEqualTo`.
* Rename methods: add `is` prefix to `greaterThan`, `greaterThanOrEqualTo`, `lessThan` and `lessThanOrEqualTo`.
* Add methods: `multipliedBy`, `isBigNumber`, `isPositive`, `integerValue`, `maximum` and `minimum`.
* Refactor test suite.
* Add *CHANGELOG.md*.
* Rewrite *bignumber.d.ts*.
* Redo API image.
#### 5.0.0
* 27/11/2017
* #81 Don't throw on constructor call without `new`.
#### 4.1.0
* 26/09/2017
* Remove node 0.6 from *.travis.yml*.
* Add *bignumber.mjs*.
#### 4.0.4
* 03/09/2017
* Add missing aliases to *bignumber.d.ts*.
#### 4.0.3
* 30/08/2017
* Add types: *bignumber.d.ts*.
#### 4.0.2
* 03/05/2017
* #120 Workaround Safari/Webkit bug.
#### 4.0.1
* 05/04/2017
* #121 BigNumber.default to BigNumber['default'].
#### 4.0.0
* 09/01/2017
* Replace BigNumber.isBigNumber method with isBigNumber prototype property.
#### 3.1.2
* 08/01/2017
* Minor documentation edit.
#### 3.1.1
* 08/01/2017
* Uncomment `isBigNumber` tests.
* Ignore dot files.
#### 3.1.0
* 08/01/2017
* Add `isBigNumber` method.
#### 3.0.2
* 08/01/2017
* Bugfix: Possible incorrect value of `ERRORS` after a `BigNumber.another` call (due to `parseNumeric` declaration in outer scope).
#### 3.0.1
* 23/11/2016
* Apply fix for old ipads with `%` issue, see #57 and #102.
* Correct error message.
#### 3.0.0
* 09/11/2016
* Remove `require('crypto')` - leave it to the user.
* Add `BigNumber.set` as `BigNumber.config` alias.
* Default `POW_PRECISION` to `0`.
#### 2.4.0
* 14/07/2016
* #97 Add exports to support ES6 imports.
#### 2.3.0
* 07/03/2016
* #86 Add modulus parameter to `toPower`.
#### 2.2.0
* 03/03/2016
* #91 Permit larger JS integers.
#### 2.1.4
* 15/12/2015
* Correct UMD.
#### 2.1.3
* 13/12/2015
* Refactor re global object and crypto availability when bundling.
#### 2.1.2
* 10/12/2015
* Bugfix: `window.crypto` not assigned to `crypto`.
#### 2.1.1
* 09/12/2015
* Prevent code bundler from adding `crypto` shim.
#### 2.1.0
* 26/10/2015
* For `valueOf` and `toJSON`, include the minus sign with negative zero.
#### 2.0.8
* 2/10/2015
* Internal round function bugfix.
#### 2.0.6
* 31/03/2015
* Add bower.json. Tweak division after in-depth review.
#### 2.0.5
* 25/03/2015
* Amend README. Remove bitcoin address.
#### 2.0.4
* 25/03/2015
* Critical bugfix #58: division.
#### 2.0.3
* 18/02/2015
* Amend README. Add source map.
#### 2.0.2
* 18/02/2015
* Correct links.
#### 2.0.1
* 18/02/2015
* Add `max`, `min`, `precision`, `random`, `shiftedBy`, `toDigits` and `truncated` methods.
* Add the short-forms: `add`, `mul`, `sd`, `sub` and `trunc`.
* Add an `another` method to enable multiple independent constructors to be created.
* Add support for the base 2, 8 and 16 prefixes `0b`, `0o` and `0x`.
* Enable a rounding mode to be specified as a second parameter to `toExponential`, `toFixed`, `toFormat` and `toPrecision`.
* Add a `CRYPTO` configuration property so cryptographically-secure pseudo-random number generation can be specified.
* Add a `MODULO_MODE` configuration property to enable the rounding mode used by the `modulo` operation to be specified.
* Add a `POW_PRECISION` configuration property to enable the number of significant digits calculated by the power operation to be limited.
* Improve code quality.
* Improve documentation.
#### 2.0.0
* 29/12/2014
* Add `dividedToIntegerBy`, `isInteger` and `toFormat` methods.
* Remove the following short-forms: `isF`, `isZ`, `toE`, `toF`, `toFr`, `toN`, `toP`, `toS`.
* Store a BigNumber's coefficient in base 1e14, rather than base 10.
* Add fast path for integers to BigNumber constructor.
* Incorporate the library into the online documentation.
#### 1.5.0
* 13/11/2014
* Add `toJSON` and `decimalPlaces` methods.
#### 1.4.1
* 08/06/2014
* Amend README.
#### 1.4.0
* 08/05/2014
* Add `toNumber`.
#### 1.3.0
* 08/11/2013
* Ensure correct rounding of `sqrt` in all, rather than almost all, cases.
* Maximum radix to 64.
#### 1.2.1
* 17/10/2013
* Sign of zero when x < 0 and x + (-x) = 0.
#### 1.2.0
* 19/9/2013
* Throw Error objects for stack.
#### 1.1.1
* 22/8/2013
* Show original value in constructor error message.
#### 1.1.0
* 1/8/2013
* Allow numbers with trailing radix point.
#### 1.0.1
* Bugfix: error messages with incorrect method name
#### 1.0.0
* 8/11/2012
* Initial release

26
node_modules/bignumber.js/LICENCE.md generated vendored Normal file
View File

@ -0,0 +1,26 @@
The MIT License (MIT)
=====================
Copyright © `<2025>` `Michael Mclaughlin`
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the “Software”), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

289
node_modules/bignumber.js/README.md generated vendored Normal file
View File

@ -0,0 +1,289 @@
![bignumber.js](https://raw.githubusercontent.com/MikeMcl/bignumber.js/gh-pages/bignumberjs.png)
A JavaScript library for arbitrary-precision decimal and non-decimal arithmetic.
[![npm version](https://img.shields.io/npm/v/bignumber.js.svg)](https://www.npmjs.com/package/bignumber.js)
[![npm downloads](https://img.shields.io/npm/dw/bignumber.js)](https://www.npmjs.com/package/bignumber.js)
[![CI](https://github.com/MikeMcl/bignumber.js/actions/workflows/ci.yml/badge.svg)](https://github.com/MikeMcl/bignumber.js/actions/workflows/ci.yml)
<br />
## Features
- Integers and decimals
- Simple API but full-featured
- Faster, smaller, and perhaps easier to use than JavaScript versions of Java's BigDecimal
- 8 KB minified and gzipped
- Replicates the `toExponential`, `toFixed`, `toPrecision` and `toString` methods of JavaScript's Number type
- Includes a `toFraction` and a correctly-rounded `squareRoot` method
- Supports cryptographically-secure pseudo-random number generation
- No dependencies
- Wide platform compatibility: uses JavaScript 1.5 (ECMAScript 3) features only
- Comprehensive [documentation](http://mikemcl.github.io/bignumber.js/) and test set
![API](https://raw.githubusercontent.com/MikeMcl/bignumber.js/gh-pages/API.png)
If a smaller and simpler library is required see [big.js](https://github.com/MikeMcl/big.js/).
It's less than half the size but only works with decimal numbers and only has half the methods.
It also has fewer configuration options than this library, and does not allow `NaN` or `Infinity`.
See also [decimal.js](https://github.com/MikeMcl/decimal.js/), which among other things adds support for non-integer powers, and performs all operations to a specified number of significant digits.
## Load
The library is the single JavaScript file *bignumber.js* or ES module *bignumber.mjs*.
### Browser
```html
<script src='path/to/bignumber.js'></script>
```
> ES module
```html
<script type="module">
import BigNumber from './path/to/bignumber.mjs';
```
> Get a minified version from a CDN:
```html
<script src='https://cdn.jsdelivr.net/npm/bignumber.js@9.3.1/bignumber.min.js'></script>
```
### [Node.js](http://nodejs.org)
```bash
npm install bignumber.js
```
```javascript
const BigNumber = require('bignumber.js');
```
> ES module
```javascript
import BigNumber from "bignumber.js";
```
### [Deno](https://deno.land/)
```javascript
// @deno-types="https://raw.githubusercontent.com/mikemcl/bignumber.js/v9.3.1/bignumber.d.mts"
import BigNumber from 'https://raw.githubusercontent.com/mikemcl/bignumber.js/v9.3.1/bignumber.mjs';
// @deno-types="https://unpkg.com/bignumber.js@latest/bignumber.d.mts"
import { BigNumber } from 'https://unpkg.com/bignumber.js@latest/bignumber.mjs';
```
## Use
The library exports a single constructor function, [`BigNumber`](http://mikemcl.github.io/bignumber.js/#bignumber), which accepts a value of type Number, String or BigNumber,
```javascript
let x = new BigNumber(123.4567);
let y = BigNumber('123456.7e-3');
let z = new BigNumber(x);
x.isEqualTo(y) && y.isEqualTo(z) && x.isEqualTo(z); // true
```
To get the string value of a BigNumber use [`toString()`](http://mikemcl.github.io/bignumber.js/#toS) or [`toFixed()`](http://mikemcl.github.io/bignumber.js/#toFix). Using `toFixed()` prevents exponential notation being returned, no matter how large or small the value.
```javascript
let x = new BigNumber('1111222233334444555566');
x.toString(); // "1.111222233334444555566e+21"
x.toFixed(); // "1111222233334444555566"
```
If the limited precision of Number values is not well understood, it is recommended to create BigNumbers from String values rather than Number values to avoid a potential loss of precision.
*In all further examples below, `let`, semicolons and `toString` calls are not shown. If a commented-out value is in quotes it means `toString` has been called on the preceding expression.*
```javascript
// Precision loss from using numeric literals with more than 15 significant digits.
new BigNumber(1.0000000000000001) // '1'
new BigNumber(88259496234518.57) // '88259496234518.56'
new BigNumber(99999999999999999999) // '100000000000000000000'
// Precision loss from using numeric literals outside the range of Number values.
new BigNumber(2e+308) // 'Infinity'
new BigNumber(1e-324) // '0'
// Precision loss from the unexpected result of arithmetic with Number values.
new BigNumber(0.7 + 0.1) // '0.7999999999999999'
```
When creating a BigNumber from a Number, note that a BigNumber is created from a Number's decimal `toString()` value not from its underlying binary value. If the latter is required, then pass the Number's `toString(2)` value and specify base 2.
```javascript
new BigNumber(Number.MAX_VALUE.toString(2), 2)
```
BigNumbers can be created from values in bases from 2 to 36. See [`ALPHABET`](http://mikemcl.github.io/bignumber.js/#alphabet) to extend this range.
```javascript
a = new BigNumber(1011, 2) // "11"
b = new BigNumber('zz.9', 36) // "1295.25"
c = a.plus(b) // "1306.25"
```
*Performance is better if base 10 is NOT specified for decimal values. Only specify base 10 when you want to limit the number of decimal places of the input value to the current [`DECIMAL_PLACES`](http://mikemcl.github.io/bignumber.js/#decimal-places) setting.*
A BigNumber is immutable in the sense that it is not changed by its methods.
```javascript
0.3 - 0.1 // 0.19999999999999998
x = new BigNumber(0.3)
x.minus(0.1) // "0.2"
x // "0.3"
```
The methods that return a BigNumber can be chained.
```javascript
x.dividedBy(y).plus(z).times(9)
x.times('1.23456780123456789e+9').plus(9876.5432321).dividedBy('4444562598.111772').integerValue()
```
Some of the longer method names have a shorter alias.
```javascript
x.squareRoot().dividedBy(y).exponentiatedBy(3).isEqualTo(x.sqrt().div(y).pow(3)) // true
x.modulo(y).multipliedBy(z).eq(x.mod(y).times(z)) // true
```
As with JavaScript's Number type, there are [`toExponential`](http://mikemcl.github.io/bignumber.js/#toE), [`toFixed`](http://mikemcl.github.io/bignumber.js/#toFix) and [`toPrecision`](http://mikemcl.github.io/bignumber.js/#toP) methods.
```javascript
x = new BigNumber(255.5)
x.toExponential(5) // "2.55500e+2"
x.toFixed(5) // "255.50000"
x.toPrecision(5) // "255.50"
x.toNumber() // 255.5
```
A base can be specified for [`toString`](http://mikemcl.github.io/bignumber.js/#toS).
*Performance is better if base 10 is NOT specified, i.e. use `toString()` not `toString(10)`. Only specify base 10 when you want to limit the number of decimal places of the string to the current [`DECIMAL_PLACES`](http://mikemcl.github.io/bignumber.js/#decimal-places) setting.*
```javascript
x.toString(16) // "ff.8"
```
There is a [`toFormat`](http://mikemcl.github.io/bignumber.js/#toFor) method which may be useful for internationalisation.
```javascript
y = new BigNumber('1234567.898765')
y.toFormat(2) // "1,234,567.90"
```
The maximum number of decimal places of the result of an operation involving division (i.e. a division, square root, base conversion or negative power operation) is set using the `set` or `config` method of the `BigNumber` constructor.
The other arithmetic operations always give the exact result.
```javascript
BigNumber.set({ DECIMAL_PLACES: 10, ROUNDING_MODE: 4 })
x = new BigNumber(2)
y = new BigNumber(3)
z = x.dividedBy(y) // "0.6666666667"
z.squareRoot() // "0.8164965809"
z.exponentiatedBy(-3) // "3.3749999995"
z.toString(2) // "0.1010101011"
z.multipliedBy(z) // "0.44444444448888888889"
z.multipliedBy(z).decimalPlaces(10) // "0.4444444445"
```
There is a [`toFraction`](http://mikemcl.github.io/bignumber.js/#toFr) method with an optional *maximum denominator* argument
```javascript
y = new BigNumber(355)
pi = y.dividedBy(113) // "3.1415929204"
pi.toFraction() // [ "7853982301", "2500000000" ]
pi.toFraction(1000) // [ "355", "113" ]
```
and [`isNaN`](http://mikemcl.github.io/bignumber.js/#isNaN) and [`isFinite`](http://mikemcl.github.io/bignumber.js/#isF) methods, as `NaN` and `Infinity` are valid `BigNumber` values.
```javascript
x = new BigNumber(NaN) // "NaN"
y = new BigNumber(Infinity) // "Infinity"
x.isNaN() && !y.isNaN() && !x.isFinite() && !y.isFinite() // true
```
The value of a BigNumber is stored in a decimal floating point format in terms of a coefficient, exponent and sign.
```javascript
x = new BigNumber(-123.456);
x.c // [ 123, 45600000000000 ] coefficient (i.e. significand)
x.e // 2 exponent
x.s // -1 sign
```
For advanced usage, multiple BigNumber constructors can be created, each with its own independent configuration.
```javascript
// Set DECIMAL_PLACES for the original BigNumber constructor
BigNumber.set({ DECIMAL_PLACES: 10 })
// Create another BigNumber constructor, optionally passing in a configuration object
BN = BigNumber.clone({ DECIMAL_PLACES: 5 })
x = new BigNumber(1)
y = new BN(1)
x.div(3) // '0.3333333333'
y.div(3) // '0.33333'
```
To avoid having to call `toString` or `valueOf` on a BigNumber to get its value in the Node.js REPL or when using `console.log` use
```javascript
BigNumber.prototype[require('util').inspect.custom] = BigNumber.prototype.valueOf;
```
For further information see the [API](http://mikemcl.github.io/bignumber.js/) reference in the *doc* directory.
## Test
The *test/modules* directory contains the test scripts for each method.
The tests can be run with Node.js or a browser. For Node.js use
```bash
npm test
```
or
```bash
node test/test
```
To test a single method, use, for example
```bash
node test/methods/toFraction
```
For the browser, open *test/test.html*.
## Minify
To minify using, for example, [terser](https://github.com/terser/terser)
```bash
npm install -g terser
```
```bash
terser big.js -c -m -o big.min.js
```
## Licence
The MIT Licence.
See [LICENCE](https://github.com/MikeMcl/bignumber.js/blob/main/LICENCE.md).

6
node_modules/bignumber.js/bignumber.d.mts generated vendored Normal file
View File

@ -0,0 +1,6 @@
/// <reference path="./types.d.ts" />
export default BigNumber;
declare const BigNumberType: typeof BigNumber;
export { BigNumberType as BigNumber };

5
node_modules/bignumber.js/bignumber.d.ts generated vendored Normal file
View File

@ -0,0 +1,5 @@
/// <reference path="./types.d.ts" />
export = BigNumber;
export as namespace BigNumber;

2922
node_modules/bignumber.js/bignumber.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

2907
node_modules/bignumber.js/bignumber.mjs generated vendored Normal file

File diff suppressed because it is too large Load Diff

2249
node_modules/bignumber.js/doc/API.html generated vendored Normal file

File diff suppressed because it is too large Load Diff

60
node_modules/bignumber.js/package.json generated vendored Normal file
View File

@ -0,0 +1,60 @@
{
"name": "bignumber.js",
"description": "A library for arbitrary-precision decimal and non-decimal arithmetic",
"version": "9.3.1",
"keywords": [
"arbitrary",
"precision",
"arithmetic",
"big",
"number",
"decimal",
"float",
"biginteger",
"bigdecimal",
"bignumber",
"bigint",
"bignum"
],
"repository": {
"type": "git",
"url": "https://github.com/MikeMcl/bignumber.js.git"
},
"main": "bignumber",
"module": "bignumber.mjs",
"browser": "bignumber.js",
"types": "bignumber.d.ts",
"exports": {
".": {
"import": {
"types": "./bignumber.d.mts",
"default": "./bignumber.mjs"
},
"require": {
"types": "./bignumber.d.ts",
"default": "./bignumber.js"
},
"browser": {
"types": "./bignumber.d.ts",
"default": "./bignumber.js"
},
"default": {
"types": "./bignumber.d.ts",
"default": "./bignumber.js"
}
},
"./package.json": "./package.json"
},
"author": {
"name": "Michael Mclaughlin",
"email": "M8ch88l@gmail.com"
},
"engines": {
"node": "*"
},
"license": "MIT",
"scripts": {
"test": "node test/test"
},
"dependencies": {}
}

1821
node_modules/bignumber.js/types.d.ts generated vendored Normal file

File diff suppressed because it is too large Load Diff

88
node_modules/data-uri-to-buffer/README.md generated vendored Normal file
View File

@ -0,0 +1,88 @@
data-uri-to-buffer
==================
### Generate a Buffer instance from a [Data URI][rfc] string
[![Build Status](https://travis-ci.org/TooTallNate/node-data-uri-to-buffer.svg?branch=master)](https://travis-ci.org/TooTallNate/node-data-uri-to-buffer)
This module accepts a ["data" URI][rfc] String of data, and returns a
node.js `Buffer` instance with the decoded data.
Installation
------------
Install with `npm`:
``` bash
$ npm install data-uri-to-buffer
```
Example
-------
``` js
import dataUriToBuffer from 'data-uri-to-buffer';
// plain-text data is supported
let uri = 'data:,Hello%2C%20World!';
let decoded = dataUriToBuffer(uri);
console.log(decoded.toString());
// 'Hello, World!'
// base64-encoded data is supported
uri = 'data:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3D';
decoded = dataUriToBuffer(uri);
console.log(decoded.toString());
// 'Hello, World!'
```
API
---
### dataUriToBuffer(String uri) → Buffer
The `type` property on the Buffer instance gets set to the main type portion of
the "mediatype" portion of the "data" URI, or defaults to `"text/plain"` if not
specified.
The `typeFull` property on the Buffer instance gets set to the entire
"mediatype" portion of the "data" URI (including all parameters), or defaults
to `"text/plain;charset=US-ASCII"` if not specified.
The `charset` property on the Buffer instance gets set to the Charset portion of
the "mediatype" portion of the "data" URI, or defaults to `"US-ASCII"` if the
entire type is not specified, or defaults to `""` otherwise.
*Note*: If the only the main type is specified but not the charset, e.g.
`"data:text/plain,abc"`, the charset is set to the empty string. The spec only
defaults to US-ASCII as charset if the entire type is not specified.
License
-------
(The MIT License)
Copyright (c) 2014 Nathan Rajlich &lt;nathan@tootallnate.net&gt;
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
[rfc]: http://tools.ietf.org/html/rfc2397

15
node_modules/data-uri-to-buffer/dist/index.d.ts generated vendored Normal file
View File

@ -0,0 +1,15 @@
/// <reference types="node" />
export interface MimeBuffer extends Buffer {
type: string;
typeFull: string;
charset: string;
}
/**
* Returns a `Buffer` instance from the given data URI `uri`.
*
* @param {String} uri Data URI to turn into a Buffer instance
* @returns {Buffer} Buffer instance from Data URI
* @api public
*/
export declare function dataUriToBuffer(uri: string): MimeBuffer;
export default dataUriToBuffer;

53
node_modules/data-uri-to-buffer/dist/index.js generated vendored Normal file
View File

@ -0,0 +1,53 @@
/**
* Returns a `Buffer` instance from the given data URI `uri`.
*
* @param {String} uri Data URI to turn into a Buffer instance
* @returns {Buffer} Buffer instance from Data URI
* @api public
*/
export function dataUriToBuffer(uri) {
if (!/^data:/i.test(uri)) {
throw new TypeError('`uri` does not appear to be a Data URI (must begin with "data:")');
}
// strip newlines
uri = uri.replace(/\r?\n/g, '');
// split the URI up into the "metadata" and the "data" portions
const firstComma = uri.indexOf(',');
if (firstComma === -1 || firstComma <= 4) {
throw new TypeError('malformed data: URI');
}
// remove the "data:" scheme and parse the metadata
const meta = uri.substring(5, firstComma).split(';');
let charset = '';
let base64 = false;
const type = meta[0] || 'text/plain';
let typeFull = type;
for (let i = 1; i < meta.length; i++) {
if (meta[i] === 'base64') {
base64 = true;
}
else if (meta[i]) {
typeFull += `;${meta[i]}`;
if (meta[i].indexOf('charset=') === 0) {
charset = meta[i].substring(8);
}
}
}
// defaults to US-ASCII only if type is not provided
if (!meta[0] && !charset.length) {
typeFull += ';charset=US-ASCII';
charset = 'US-ASCII';
}
// get the encoded data portion and decode URI-encoded chars
const encoding = base64 ? 'base64' : 'ascii';
const data = unescape(uri.substring(firstComma + 1));
const buffer = Buffer.from(data, encoding);
// set `.type` and `.typeFull` properties to MIME type
buffer.type = type;
buffer.typeFull = typeFull;
// set the `.charset` property
buffer.charset = charset;
return buffer;
}
export default dataUriToBuffer;
//# sourceMappingURL=index.js.map

1
node_modules/data-uri-to-buffer/dist/index.js.map generated vendored Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,GAAW;IAC1C,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;QACzB,MAAM,IAAI,SAAS,CAClB,kEAAkE,CAClE,CAAC;KACF;IAED,iBAAiB;IACjB,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAEhC,+DAA+D;IAC/D,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACpC,IAAI,UAAU,KAAK,CAAC,CAAC,IAAI,UAAU,IAAI,CAAC,EAAE;QACzC,MAAM,IAAI,SAAS,CAAC,qBAAqB,CAAC,CAAC;KAC3C;IAED,mDAAmD;IACnD,MAAM,IAAI,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAErD,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,YAAY,CAAC;IACrC,IAAI,QAAQ,GAAG,IAAI,CAAC;IACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACrC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE;YACzB,MAAM,GAAG,IAAI,CAAC;SACd;aAAM,IAAG,IAAI,CAAC,CAAC,CAAC,EAAE;YAClB,QAAQ,IAAI,IAAM,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5B,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE;gBACtC,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;aAC/B;SACD;KACD;IACD,oDAAoD;IACpD,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE;QAChC,QAAQ,IAAI,mBAAmB,CAAC;QAChC,OAAO,GAAG,UAAU,CAAC;KACrB;IAED,4DAA4D;IAC5D,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC;IAC7C,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC;IACrD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAe,CAAC;IAEzD,sDAAsD;IACtD,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAE3B,8BAA8B;IAC9B,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;IAEzB,OAAO,MAAM,CAAC;AACf,CAAC;AAED,eAAe,eAAe,CAAC"}

62
node_modules/data-uri-to-buffer/package.json generated vendored Normal file
View File

@ -0,0 +1,62 @@
{
"name": "data-uri-to-buffer",
"version": "4.0.1",
"description": "Generate a Buffer instance from a Data URI string",
"type": "module",
"exports": "./dist/index.js",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
"dist",
"src"
],
"scripts": {
"build": "tsc",
"test": "jest",
"prepublishOnly": "npm run build"
},
"repository": {
"type": "git",
"url": "git://github.com/TooTallNate/node-data-uri-to-buffer.git"
},
"engines": {
"node": ">= 12"
},
"keywords": [
"data",
"uri",
"datauri",
"data-uri",
"buffer",
"convert",
"rfc2397",
"2397"
],
"author": "Nathan Rajlich <nathan@tootallnate.net> (http://n8.io/)",
"license": "MIT",
"bugs": {
"url": "https://github.com/TooTallNate/node-data-uri-to-buffer/issues"
},
"homepage": "https://github.com/TooTallNate/node-data-uri-to-buffer",
"devDependencies": {
"@types/jest": "^27.0.2",
"@types/node": "^12.20.36",
"jest": "^27.3.1",
"ts-jest": "^27.0.7",
"typescript": "^4.4.4"
},
"jest": {
"preset": "ts-jest",
"globals": {
"ts-jest": {
"diagnostics": false,
"isolatedModules": true
}
},
"verbose": false,
"testEnvironment": "node",
"testMatch": [
"<rootDir>/test/**/*.test.ts"
]
}
}

68
node_modules/data-uri-to-buffer/src/index.ts generated vendored Normal file
View File

@ -0,0 +1,68 @@
export interface MimeBuffer extends Buffer {
type: string;
typeFull: string;
charset: string;
}
/**
* Returns a `Buffer` instance from the given data URI `uri`.
*
* @param {String} uri Data URI to turn into a Buffer instance
* @returns {Buffer} Buffer instance from Data URI
* @api public
*/
export function dataUriToBuffer(uri: string): MimeBuffer {
if (!/^data:/i.test(uri)) {
throw new TypeError(
'`uri` does not appear to be a Data URI (must begin with "data:")'
);
}
// strip newlines
uri = uri.replace(/\r?\n/g, '');
// split the URI up into the "metadata" and the "data" portions
const firstComma = uri.indexOf(',');
if (firstComma === -1 || firstComma <= 4) {
throw new TypeError('malformed data: URI');
}
// remove the "data:" scheme and parse the metadata
const meta = uri.substring(5, firstComma).split(';');
let charset = '';
let base64 = false;
const type = meta[0] || 'text/plain';
let typeFull = type;
for (let i = 1; i < meta.length; i++) {
if (meta[i] === 'base64') {
base64 = true;
} else if(meta[i]) {
typeFull += `;${ meta[i]}`;
if (meta[i].indexOf('charset=') === 0) {
charset = meta[i].substring(8);
}
}
}
// defaults to US-ASCII only if type is not provided
if (!meta[0] && !charset.length) {
typeFull += ';charset=US-ASCII';
charset = 'US-ASCII';
}
// get the encoded data portion and decode URI-encoded chars
const encoding = base64 ? 'base64' : 'ascii';
const data = unescape(uri.substring(firstComma + 1));
const buffer = Buffer.from(data, encoding) as MimeBuffer;
// set `.type` and `.typeFull` properties to MIME type
buffer.type = type;
buffer.typeFull = typeFull;
// set the `.charset` property
buffer.charset = charset;
return buffer;
}
export default dataUriToBuffer;

2844
node_modules/date-fns/CHANGELOG.md generated vendored Normal file

File diff suppressed because it is too large Load Diff

21
node_modules/date-fns/LICENSE.md generated vendored Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 Sasha Koss and Lesha Koss https://kossnocorp.mit-license.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

58
node_modules/date-fns/README.md generated vendored Normal file
View File

@ -0,0 +1,58 @@
🔥️ **NEW**: [date-fns v4.0 with first-class time zone support is out!](https://blog.date-fns.org/v40-with-time-zone-support/)
<img alt="date-fns" title="date-fns" src="https://raw.githubusercontent.com/date-fns/date-fns/master/docs/logotype.svg" width="150" />
date-fns provides the most comprehensive, yet simple and consistent toolset for manipulating JavaScript dates in a browser & Node.js
👉 [Documentation](https://date-fns.org/)
👉 [Blog](https://blog.date-fns.org/)
<hr>
It's like [Lodash](https://lodash.com) for dates
- It has [**200+ functions** for all occasions](https://date-fns.org/docs/Getting-Started/).
- **Modular**: Pick what you need. Works with webpack, Browserify, or Rollup and also supports tree-shaking.
- **Native dates**: Uses existing native type. It doesn't extend core objects for safety's sake.
- **Immutable & Pure**: Built using pure functions and always returns a new date instance.
- **TypeScript**: The library is 100% TypeScript with brand-new handcrafted types.
- **I18n**: Dozens of locales. Include only what you need.
- [and many more benefits](https://date-fns.org/)
```js
import { compareAsc, format } from "date-fns";
format(new Date(2014, 1, 11), "yyyy-MM-dd");
//=> '2014-02-11'
const dates = [
new Date(1995, 6, 2),
new Date(1987, 1, 11),
new Date(1989, 6, 10),
];
dates.sort(compareAsc);
//=> [
// Wed Feb 11 1987 00:00:00,
// Mon Jul 10 1989 00:00:00,
// Sun Jul 02 1995 00:00:00
// ]
```
The library is available as an [npm package](https://www.npmjs.com/package/date-fns).
To install the package run:
```bash
npm install date-fns --save
```
## Docs
[See date-fns.org](https://date-fns.org/) for more details, API,
and other docs.
<br />
## License
[MIT © Sasha Koss](https://kossnocorp.mit-license.org/)

12
node_modules/date-fns/SECURITY.md generated vendored Normal file
View File

@ -0,0 +1,12 @@
# Security Policy
## Supported Versions
Security updates are applied only to the latest release.
## Reporting a Vulnerability
If you have discovered a security vulnerability in this project, please report it privately. **Do not disclose it as a public issue.**
This gives us time to work with you to fix the issue before public exposure, reducing the chance that the exploit will be used before a patch is released.
Please disclose it to [Sasha Koss](mailto:koss@nocorp.me). This project is maintained by a team of volunteers
on a reasonable-effort basis. As such, please give us at least 90 days to work on a fix before public exposure.

7
node_modules/date-fns/_lib/addLeadingZeros.cjs generated vendored Normal file
View File

@ -0,0 +1,7 @@
"use strict";
exports.addLeadingZeros = addLeadingZeros;
function addLeadingZeros(number, targetLength) {
const sign = number < 0 ? "-" : "";
const output = Math.abs(number).toString().padStart(targetLength, "0");
return sign + output;
}

4
node_modules/date-fns/_lib/addLeadingZeros.d.cts generated vendored Normal file
View File

@ -0,0 +1,4 @@
export declare function addLeadingZeros(
number: number,
targetLength: number,
): string;

4
node_modules/date-fns/_lib/addLeadingZeros.d.ts generated vendored Normal file
View File

@ -0,0 +1,4 @@
export declare function addLeadingZeros(
number: number,
targetLength: number,
): string;

5
node_modules/date-fns/_lib/addLeadingZeros.js generated vendored Normal file
View File

@ -0,0 +1,5 @@
export function addLeadingZeros(number, targetLength) {
const sign = number < 0 ? "-" : "";
const output = Math.abs(number).toString().padStart(targetLength, "0");
return sign + output;
}

8
node_modules/date-fns/_lib/defaultLocale.cjs generated vendored Normal file
View File

@ -0,0 +1,8 @@
"use strict";
Object.defineProperty(exports, "defaultLocale", {
enumerable: true,
get: function () {
return _index.enUS;
},
});
var _index = require("../locale/en-US.cjs");

1
node_modules/date-fns/_lib/defaultLocale.d.cts generated vendored Normal file
View File

@ -0,0 +1 @@
export { enUS as defaultLocale } from "../locale/en-US.js";

1
node_modules/date-fns/_lib/defaultLocale.d.ts generated vendored Normal file
View File

@ -0,0 +1 @@
export { enUS as defaultLocale } from "../locale/en-US.js";

1
node_modules/date-fns/_lib/defaultLocale.js generated vendored Normal file
View File

@ -0,0 +1 @@
export { enUS as defaultLocale } from "../locale/en-US.js";

13
node_modules/date-fns/_lib/defaultOptions.cjs generated vendored Normal file
View File

@ -0,0 +1,13 @@
"use strict";
exports.getDefaultOptions = getDefaultOptions;
exports.setDefaultOptions = setDefaultOptions;
let defaultOptions = {};
function getDefaultOptions() {
return defaultOptions;
}
function setDefaultOptions(newOptions) {
defaultOptions = newOptions;
}

11
node_modules/date-fns/_lib/defaultOptions.d.cts generated vendored Normal file
View File

@ -0,0 +1,11 @@
import type {
FirstWeekContainsDateOptions,
Locale,
LocalizedOptions,
WeekOptions,
} from "../types.js";
export type DefaultOptions = LocalizedOptions<keyof Locale> &
WeekOptions &
FirstWeekContainsDateOptions;
export declare function getDefaultOptions(): DefaultOptions;
export declare function setDefaultOptions(newOptions: DefaultOptions): void;

11
node_modules/date-fns/_lib/defaultOptions.d.ts generated vendored Normal file
View File

@ -0,0 +1,11 @@
import type {
FirstWeekContainsDateOptions,
Locale,
LocalizedOptions,
WeekOptions,
} from "../types.js";
export type DefaultOptions = LocalizedOptions<keyof Locale> &
WeekOptions &
FirstWeekContainsDateOptions;
export declare function getDefaultOptions(): DefaultOptions;
export declare function setDefaultOptions(newOptions: DefaultOptions): void;

9
node_modules/date-fns/_lib/defaultOptions.js generated vendored Normal file
View File

@ -0,0 +1,9 @@
let defaultOptions = {};
export function getDefaultOptions() {
return defaultOptions;
}
export function setDefaultOptions(newOptions) {
defaultOptions = newOptions;
}

780
node_modules/date-fns/_lib/format/formatters.cjs generated vendored Normal file
View File

@ -0,0 +1,780 @@
"use strict";
exports.formatters = void 0;
var _index = require("../../getDayOfYear.cjs");
var _index2 = require("../../getISOWeek.cjs");
var _index3 = require("../../getISOWeekYear.cjs");
var _index4 = require("../../getWeek.cjs");
var _index5 = require("../../getWeekYear.cjs");
var _index6 = require("../addLeadingZeros.cjs");
var _index7 = require("./lightFormatters.cjs");
const dayPeriodEnum = {
am: "am",
pm: "pm",
midnight: "midnight",
noon: "noon",
morning: "morning",
afternoon: "afternoon",
evening: "evening",
night: "night",
};
/*
* | | Unit | | Unit |
* |-----|--------------------------------|-----|--------------------------------|
* | a | AM, PM | A* | Milliseconds in day |
* | b | AM, PM, noon, midnight | B | Flexible day period |
* | c | Stand-alone local day of week | C* | Localized hour w/ day period |
* | d | Day of month | D | Day of year |
* | e | Local day of week | E | Day of week |
* | f | | F* | Day of week in month |
* | g* | Modified Julian day | G | Era |
* | h | Hour [1-12] | H | Hour [0-23] |
* | i! | ISO day of week | I! | ISO week of year |
* | j* | Localized hour w/ day period | J* | Localized hour w/o day period |
* | k | Hour [1-24] | K | Hour [0-11] |
* | l* | (deprecated) | L | Stand-alone month |
* | m | Minute | M | Month |
* | n | | N | |
* | o! | Ordinal number modifier | O | Timezone (GMT) |
* | p! | Long localized time | P! | Long localized date |
* | q | Stand-alone quarter | Q | Quarter |
* | r* | Related Gregorian year | R! | ISO week-numbering year |
* | s | Second | S | Fraction of second |
* | t! | Seconds timestamp | T! | Milliseconds timestamp |
* | u | Extended year | U* | Cyclic year |
* | v* | Timezone (generic non-locat.) | V* | Timezone (location) |
* | w | Local week of year | W* | Week of month |
* | x | Timezone (ISO-8601 w/o Z) | X | Timezone (ISO-8601) |
* | y | Year (abs) | Y | Local week-numbering year |
* | z | Timezone (specific non-locat.) | Z* | Timezone (aliases) |
*
* Letters marked by * are not implemented but reserved by Unicode standard.
*
* Letters marked by ! are non-standard, but implemented by date-fns:
* - `o` modifies the previous token to turn it into an ordinal (see `format` docs)
* - `i` is ISO day of week. For `i` and `ii` is returns numeric ISO week days,
* i.e. 7 for Sunday, 1 for Monday, etc.
* - `I` is ISO week of year, as opposed to `w` which is local week of year.
* - `R` is ISO week-numbering year, as opposed to `Y` which is local week-numbering year.
* `R` is supposed to be used in conjunction with `I` and `i`
* for universal ISO week-numbering date, whereas
* `Y` is supposed to be used in conjunction with `w` and `e`
* for week-numbering date specific to the locale.
* - `P` is long localized date format
* - `p` is long localized time format
*/
const formatters = (exports.formatters = {
// Era
G: function (date, token, localize) {
const era = date.getFullYear() > 0 ? 1 : 0;
switch (token) {
// AD, BC
case "G":
case "GG":
case "GGG":
return localize.era(era, { width: "abbreviated" });
// A, B
case "GGGGG":
return localize.era(era, { width: "narrow" });
// Anno Domini, Before Christ
case "GGGG":
default:
return localize.era(era, { width: "wide" });
}
},
// Year
y: function (date, token, localize) {
// Ordinal number
if (token === "yo") {
const signedYear = date.getFullYear();
// Returns 1 for 1 BC (which is year 0 in JavaScript)
const year = signedYear > 0 ? signedYear : 1 - signedYear;
return localize.ordinalNumber(year, { unit: "year" });
}
return _index7.lightFormatters.y(date, token);
},
// Local week-numbering year
Y: function (date, token, localize, options) {
const signedWeekYear = (0, _index5.getWeekYear)(date, options);
// Returns 1 for 1 BC (which is year 0 in JavaScript)
const weekYear = signedWeekYear > 0 ? signedWeekYear : 1 - signedWeekYear;
// Two digit year
if (token === "YY") {
const twoDigitYear = weekYear % 100;
return (0, _index6.addLeadingZeros)(twoDigitYear, 2);
}
// Ordinal number
if (token === "Yo") {
return localize.ordinalNumber(weekYear, { unit: "year" });
}
// Padding
return (0, _index6.addLeadingZeros)(weekYear, token.length);
},
// ISO week-numbering year
R: function (date, token) {
const isoWeekYear = (0, _index3.getISOWeekYear)(date);
// Padding
return (0, _index6.addLeadingZeros)(isoWeekYear, token.length);
},
// Extended year. This is a single number designating the year of this calendar system.
// The main difference between `y` and `u` localizers are B.C. years:
// | Year | `y` | `u` |
// |------|-----|-----|
// | AC 1 | 1 | 1 |
// | BC 1 | 1 | 0 |
// | BC 2 | 2 | -1 |
// Also `yy` always returns the last two digits of a year,
// while `uu` pads single digit years to 2 characters and returns other years unchanged.
u: function (date, token) {
const year = date.getFullYear();
return (0, _index6.addLeadingZeros)(year, token.length);
},
// Quarter
Q: function (date, token, localize) {
const quarter = Math.ceil((date.getMonth() + 1) / 3);
switch (token) {
// 1, 2, 3, 4
case "Q":
return String(quarter);
// 01, 02, 03, 04
case "QQ":
return (0, _index6.addLeadingZeros)(quarter, 2);
// 1st, 2nd, 3rd, 4th
case "Qo":
return localize.ordinalNumber(quarter, { unit: "quarter" });
// Q1, Q2, Q3, Q4
case "QQQ":
return localize.quarter(quarter, {
width: "abbreviated",
context: "formatting",
});
// 1, 2, 3, 4 (narrow quarter; could be not numerical)
case "QQQQQ":
return localize.quarter(quarter, {
width: "narrow",
context: "formatting",
});
// 1st quarter, 2nd quarter, ...
case "QQQQ":
default:
return localize.quarter(quarter, {
width: "wide",
context: "formatting",
});
}
},
// Stand-alone quarter
q: function (date, token, localize) {
const quarter = Math.ceil((date.getMonth() + 1) / 3);
switch (token) {
// 1, 2, 3, 4
case "q":
return String(quarter);
// 01, 02, 03, 04
case "qq":
return (0, _index6.addLeadingZeros)(quarter, 2);
// 1st, 2nd, 3rd, 4th
case "qo":
return localize.ordinalNumber(quarter, { unit: "quarter" });
// Q1, Q2, Q3, Q4
case "qqq":
return localize.quarter(quarter, {
width: "abbreviated",
context: "standalone",
});
// 1, 2, 3, 4 (narrow quarter; could be not numerical)
case "qqqqq":
return localize.quarter(quarter, {
width: "narrow",
context: "standalone",
});
// 1st quarter, 2nd quarter, ...
case "qqqq":
default:
return localize.quarter(quarter, {
width: "wide",
context: "standalone",
});
}
},
// Month
M: function (date, token, localize) {
const month = date.getMonth();
switch (token) {
case "M":
case "MM":
return _index7.lightFormatters.M(date, token);
// 1st, 2nd, ..., 12th
case "Mo":
return localize.ordinalNumber(month + 1, { unit: "month" });
// Jan, Feb, ..., Dec
case "MMM":
return localize.month(month, {
width: "abbreviated",
context: "formatting",
});
// J, F, ..., D
case "MMMMM":
return localize.month(month, {
width: "narrow",
context: "formatting",
});
// January, February, ..., December
case "MMMM":
default:
return localize.month(month, { width: "wide", context: "formatting" });
}
},
// Stand-alone month
L: function (date, token, localize) {
const month = date.getMonth();
switch (token) {
// 1, 2, ..., 12
case "L":
return String(month + 1);
// 01, 02, ..., 12
case "LL":
return (0, _index6.addLeadingZeros)(month + 1, 2);
// 1st, 2nd, ..., 12th
case "Lo":
return localize.ordinalNumber(month + 1, { unit: "month" });
// Jan, Feb, ..., Dec
case "LLL":
return localize.month(month, {
width: "abbreviated",
context: "standalone",
});
// J, F, ..., D
case "LLLLL":
return localize.month(month, {
width: "narrow",
context: "standalone",
});
// January, February, ..., December
case "LLLL":
default:
return localize.month(month, { width: "wide", context: "standalone" });
}
},
// Local week of year
w: function (date, token, localize, options) {
const week = (0, _index4.getWeek)(date, options);
if (token === "wo") {
return localize.ordinalNumber(week, { unit: "week" });
}
return (0, _index6.addLeadingZeros)(week, token.length);
},
// ISO week of year
I: function (date, token, localize) {
const isoWeek = (0, _index2.getISOWeek)(date);
if (token === "Io") {
return localize.ordinalNumber(isoWeek, { unit: "week" });
}
return (0, _index6.addLeadingZeros)(isoWeek, token.length);
},
// Day of the month
d: function (date, token, localize) {
if (token === "do") {
return localize.ordinalNumber(date.getDate(), { unit: "date" });
}
return _index7.lightFormatters.d(date, token);
},
// Day of year
D: function (date, token, localize) {
const dayOfYear = (0, _index.getDayOfYear)(date);
if (token === "Do") {
return localize.ordinalNumber(dayOfYear, { unit: "dayOfYear" });
}
return (0, _index6.addLeadingZeros)(dayOfYear, token.length);
},
// Day of week
E: function (date, token, localize) {
const dayOfWeek = date.getDay();
switch (token) {
// Tue
case "E":
case "EE":
case "EEE":
return localize.day(dayOfWeek, {
width: "abbreviated",
context: "formatting",
});
// T
case "EEEEE":
return localize.day(dayOfWeek, {
width: "narrow",
context: "formatting",
});
// Tu
case "EEEEEE":
return localize.day(dayOfWeek, {
width: "short",
context: "formatting",
});
// Tuesday
case "EEEE":
default:
return localize.day(dayOfWeek, {
width: "wide",
context: "formatting",
});
}
},
// Local day of week
e: function (date, token, localize, options) {
const dayOfWeek = date.getDay();
const localDayOfWeek = (dayOfWeek - options.weekStartsOn + 8) % 7 || 7;
switch (token) {
// Numerical value (Nth day of week with current locale or weekStartsOn)
case "e":
return String(localDayOfWeek);
// Padded numerical value
case "ee":
return (0, _index6.addLeadingZeros)(localDayOfWeek, 2);
// 1st, 2nd, ..., 7th
case "eo":
return localize.ordinalNumber(localDayOfWeek, { unit: "day" });
case "eee":
return localize.day(dayOfWeek, {
width: "abbreviated",
context: "formatting",
});
// T
case "eeeee":
return localize.day(dayOfWeek, {
width: "narrow",
context: "formatting",
});
// Tu
case "eeeeee":
return localize.day(dayOfWeek, {
width: "short",
context: "formatting",
});
// Tuesday
case "eeee":
default:
return localize.day(dayOfWeek, {
width: "wide",
context: "formatting",
});
}
},
// Stand-alone local day of week
c: function (date, token, localize, options) {
const dayOfWeek = date.getDay();
const localDayOfWeek = (dayOfWeek - options.weekStartsOn + 8) % 7 || 7;
switch (token) {
// Numerical value (same as in `e`)
case "c":
return String(localDayOfWeek);
// Padded numerical value
case "cc":
return (0, _index6.addLeadingZeros)(localDayOfWeek, token.length);
// 1st, 2nd, ..., 7th
case "co":
return localize.ordinalNumber(localDayOfWeek, { unit: "day" });
case "ccc":
return localize.day(dayOfWeek, {
width: "abbreviated",
context: "standalone",
});
// T
case "ccccc":
return localize.day(dayOfWeek, {
width: "narrow",
context: "standalone",
});
// Tu
case "cccccc":
return localize.day(dayOfWeek, {
width: "short",
context: "standalone",
});
// Tuesday
case "cccc":
default:
return localize.day(dayOfWeek, {
width: "wide",
context: "standalone",
});
}
},
// ISO day of week
i: function (date, token, localize) {
const dayOfWeek = date.getDay();
const isoDayOfWeek = dayOfWeek === 0 ? 7 : dayOfWeek;
switch (token) {
// 2
case "i":
return String(isoDayOfWeek);
// 02
case "ii":
return (0, _index6.addLeadingZeros)(isoDayOfWeek, token.length);
// 2nd
case "io":
return localize.ordinalNumber(isoDayOfWeek, { unit: "day" });
// Tue
case "iii":
return localize.day(dayOfWeek, {
width: "abbreviated",
context: "formatting",
});
// T
case "iiiii":
return localize.day(dayOfWeek, {
width: "narrow",
context: "formatting",
});
// Tu
case "iiiiii":
return localize.day(dayOfWeek, {
width: "short",
context: "formatting",
});
// Tuesday
case "iiii":
default:
return localize.day(dayOfWeek, {
width: "wide",
context: "formatting",
});
}
},
// AM or PM
a: function (date, token, localize) {
const hours = date.getHours();
const dayPeriodEnumValue = hours / 12 >= 1 ? "pm" : "am";
switch (token) {
case "a":
case "aa":
return localize.dayPeriod(dayPeriodEnumValue, {
width: "abbreviated",
context: "formatting",
});
case "aaa":
return localize
.dayPeriod(dayPeriodEnumValue, {
width: "abbreviated",
context: "formatting",
})
.toLowerCase();
case "aaaaa":
return localize.dayPeriod(dayPeriodEnumValue, {
width: "narrow",
context: "formatting",
});
case "aaaa":
default:
return localize.dayPeriod(dayPeriodEnumValue, {
width: "wide",
context: "formatting",
});
}
},
// AM, PM, midnight, noon
b: function (date, token, localize) {
const hours = date.getHours();
let dayPeriodEnumValue;
if (hours === 12) {
dayPeriodEnumValue = dayPeriodEnum.noon;
} else if (hours === 0) {
dayPeriodEnumValue = dayPeriodEnum.midnight;
} else {
dayPeriodEnumValue = hours / 12 >= 1 ? "pm" : "am";
}
switch (token) {
case "b":
case "bb":
return localize.dayPeriod(dayPeriodEnumValue, {
width: "abbreviated",
context: "formatting",
});
case "bbb":
return localize
.dayPeriod(dayPeriodEnumValue, {
width: "abbreviated",
context: "formatting",
})
.toLowerCase();
case "bbbbb":
return localize.dayPeriod(dayPeriodEnumValue, {
width: "narrow",
context: "formatting",
});
case "bbbb":
default:
return localize.dayPeriod(dayPeriodEnumValue, {
width: "wide",
context: "formatting",
});
}
},
// in the morning, in the afternoon, in the evening, at night
B: function (date, token, localize) {
const hours = date.getHours();
let dayPeriodEnumValue;
if (hours >= 17) {
dayPeriodEnumValue = dayPeriodEnum.evening;
} else if (hours >= 12) {
dayPeriodEnumValue = dayPeriodEnum.afternoon;
} else if (hours >= 4) {
dayPeriodEnumValue = dayPeriodEnum.morning;
} else {
dayPeriodEnumValue = dayPeriodEnum.night;
}
switch (token) {
case "B":
case "BB":
case "BBB":
return localize.dayPeriod(dayPeriodEnumValue, {
width: "abbreviated",
context: "formatting",
});
case "BBBBB":
return localize.dayPeriod(dayPeriodEnumValue, {
width: "narrow",
context: "formatting",
});
case "BBBB":
default:
return localize.dayPeriod(dayPeriodEnumValue, {
width: "wide",
context: "formatting",
});
}
},
// Hour [1-12]
h: function (date, token, localize) {
if (token === "ho") {
let hours = date.getHours() % 12;
if (hours === 0) hours = 12;
return localize.ordinalNumber(hours, { unit: "hour" });
}
return _index7.lightFormatters.h(date, token);
},
// Hour [0-23]
H: function (date, token, localize) {
if (token === "Ho") {
return localize.ordinalNumber(date.getHours(), { unit: "hour" });
}
return _index7.lightFormatters.H(date, token);
},
// Hour [0-11]
K: function (date, token, localize) {
const hours = date.getHours() % 12;
if (token === "Ko") {
return localize.ordinalNumber(hours, { unit: "hour" });
}
return (0, _index6.addLeadingZeros)(hours, token.length);
},
// Hour [1-24]
k: function (date, token, localize) {
let hours = date.getHours();
if (hours === 0) hours = 24;
if (token === "ko") {
return localize.ordinalNumber(hours, { unit: "hour" });
}
return (0, _index6.addLeadingZeros)(hours, token.length);
},
// Minute
m: function (date, token, localize) {
if (token === "mo") {
return localize.ordinalNumber(date.getMinutes(), { unit: "minute" });
}
return _index7.lightFormatters.m(date, token);
},
// Second
s: function (date, token, localize) {
if (token === "so") {
return localize.ordinalNumber(date.getSeconds(), { unit: "second" });
}
return _index7.lightFormatters.s(date, token);
},
// Fraction of second
S: function (date, token) {
return _index7.lightFormatters.S(date, token);
},
// Timezone (ISO-8601. If offset is 0, output is always `'Z'`)
X: function (date, token, _localize) {
const timezoneOffset = date.getTimezoneOffset();
if (timezoneOffset === 0) {
return "Z";
}
switch (token) {
// Hours and optional minutes
case "X":
return formatTimezoneWithOptionalMinutes(timezoneOffset);
// Hours, minutes and optional seconds without `:` delimiter
// Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets
// so this token always has the same output as `XX`
case "XXXX":
case "XX": // Hours and minutes without `:` delimiter
return formatTimezone(timezoneOffset);
// Hours, minutes and optional seconds with `:` delimiter
// Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets
// so this token always has the same output as `XXX`
case "XXXXX":
case "XXX": // Hours and minutes with `:` delimiter
default:
return formatTimezone(timezoneOffset, ":");
}
},
// Timezone (ISO-8601. If offset is 0, output is `'+00:00'` or equivalent)
x: function (date, token, _localize) {
const timezoneOffset = date.getTimezoneOffset();
switch (token) {
// Hours and optional minutes
case "x":
return formatTimezoneWithOptionalMinutes(timezoneOffset);
// Hours, minutes and optional seconds without `:` delimiter
// Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets
// so this token always has the same output as `xx`
case "xxxx":
case "xx": // Hours and minutes without `:` delimiter
return formatTimezone(timezoneOffset);
// Hours, minutes and optional seconds with `:` delimiter
// Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets
// so this token always has the same output as `xxx`
case "xxxxx":
case "xxx": // Hours and minutes with `:` delimiter
default:
return formatTimezone(timezoneOffset, ":");
}
},
// Timezone (GMT)
O: function (date, token, _localize) {
const timezoneOffset = date.getTimezoneOffset();
switch (token) {
// Short
case "O":
case "OO":
case "OOO":
return "GMT" + formatTimezoneShort(timezoneOffset, ":");
// Long
case "OOOO":
default:
return "GMT" + formatTimezone(timezoneOffset, ":");
}
},
// Timezone (specific non-location)
z: function (date, token, _localize) {
const timezoneOffset = date.getTimezoneOffset();
switch (token) {
// Short
case "z":
case "zz":
case "zzz":
return "GMT" + formatTimezoneShort(timezoneOffset, ":");
// Long
case "zzzz":
default:
return "GMT" + formatTimezone(timezoneOffset, ":");
}
},
// Seconds timestamp
t: function (date, token, _localize) {
const timestamp = Math.trunc(+date / 1000);
return (0, _index6.addLeadingZeros)(timestamp, token.length);
},
// Milliseconds timestamp
T: function (date, token, _localize) {
return (0, _index6.addLeadingZeros)(+date, token.length);
},
});
function formatTimezoneShort(offset, delimiter = "") {
const sign = offset > 0 ? "-" : "+";
const absOffset = Math.abs(offset);
const hours = Math.trunc(absOffset / 60);
const minutes = absOffset % 60;
if (minutes === 0) {
return sign + String(hours);
}
return (
sign + String(hours) + delimiter + (0, _index6.addLeadingZeros)(minutes, 2)
);
}
function formatTimezoneWithOptionalMinutes(offset, delimiter) {
if (offset % 60 === 0) {
const sign = offset > 0 ? "-" : "+";
return sign + (0, _index6.addLeadingZeros)(Math.abs(offset) / 60, 2);
}
return formatTimezone(offset, delimiter);
}
function formatTimezone(offset, delimiter = "") {
const sign = offset > 0 ? "-" : "+";
const absOffset = Math.abs(offset);
const hours = (0, _index6.addLeadingZeros)(Math.trunc(absOffset / 60), 2);
const minutes = (0, _index6.addLeadingZeros)(absOffset % 60, 2);
return sign + hours + delimiter + minutes;
}

18
node_modules/date-fns/_lib/format/formatters.d.cts generated vendored Normal file
View File

@ -0,0 +1,18 @@
import type { Localize } from "../../locale/types.js";
import type {
FirstWeekContainsDateOptions,
LocalizedOptions,
WeekOptions,
} from "../../types.js";
type Formatter = (
date: Date,
token: string,
localize: Localize,
options: Required<
LocalizedOptions<"options"> & WeekOptions & FirstWeekContainsDateOptions
>,
) => string;
export declare const formatters: {
[token: string]: Formatter;
};
export {};

18
node_modules/date-fns/_lib/format/formatters.d.ts generated vendored Normal file
View File

@ -0,0 +1,18 @@
import type { Localize } from "../../locale/types.js";
import type {
FirstWeekContainsDateOptions,
LocalizedOptions,
WeekOptions,
} from "../../types.js";
type Formatter = (
date: Date,
token: string,
localize: Localize,
options: Required<
LocalizedOptions<"options"> & WeekOptions & FirstWeekContainsDateOptions
>,
) => string;
export declare const formatters: {
[token: string]: Formatter;
};
export {};

776
node_modules/date-fns/_lib/format/formatters.js generated vendored Normal file
View File

@ -0,0 +1,776 @@
import { getDayOfYear } from "../../getDayOfYear.js";
import { getISOWeek } from "../../getISOWeek.js";
import { getISOWeekYear } from "../../getISOWeekYear.js";
import { getWeek } from "../../getWeek.js";
import { getWeekYear } from "../../getWeekYear.js";
import { addLeadingZeros } from "../addLeadingZeros.js";
import { lightFormatters } from "./lightFormatters.js";
const dayPeriodEnum = {
am: "am",
pm: "pm",
midnight: "midnight",
noon: "noon",
morning: "morning",
afternoon: "afternoon",
evening: "evening",
night: "night",
};
/*
* | | Unit | | Unit |
* |-----|--------------------------------|-----|--------------------------------|
* | a | AM, PM | A* | Milliseconds in day |
* | b | AM, PM, noon, midnight | B | Flexible day period |
* | c | Stand-alone local day of week | C* | Localized hour w/ day period |
* | d | Day of month | D | Day of year |
* | e | Local day of week | E | Day of week |
* | f | | F* | Day of week in month |
* | g* | Modified Julian day | G | Era |
* | h | Hour [1-12] | H | Hour [0-23] |
* | i! | ISO day of week | I! | ISO week of year |
* | j* | Localized hour w/ day period | J* | Localized hour w/o day period |
* | k | Hour [1-24] | K | Hour [0-11] |
* | l* | (deprecated) | L | Stand-alone month |
* | m | Minute | M | Month |
* | n | | N | |
* | o! | Ordinal number modifier | O | Timezone (GMT) |
* | p! | Long localized time | P! | Long localized date |
* | q | Stand-alone quarter | Q | Quarter |
* | r* | Related Gregorian year | R! | ISO week-numbering year |
* | s | Second | S | Fraction of second |
* | t! | Seconds timestamp | T! | Milliseconds timestamp |
* | u | Extended year | U* | Cyclic year |
* | v* | Timezone (generic non-locat.) | V* | Timezone (location) |
* | w | Local week of year | W* | Week of month |
* | x | Timezone (ISO-8601 w/o Z) | X | Timezone (ISO-8601) |
* | y | Year (abs) | Y | Local week-numbering year |
* | z | Timezone (specific non-locat.) | Z* | Timezone (aliases) |
*
* Letters marked by * are not implemented but reserved by Unicode standard.
*
* Letters marked by ! are non-standard, but implemented by date-fns:
* - `o` modifies the previous token to turn it into an ordinal (see `format` docs)
* - `i` is ISO day of week. For `i` and `ii` is returns numeric ISO week days,
* i.e. 7 for Sunday, 1 for Monday, etc.
* - `I` is ISO week of year, as opposed to `w` which is local week of year.
* - `R` is ISO week-numbering year, as opposed to `Y` which is local week-numbering year.
* `R` is supposed to be used in conjunction with `I` and `i`
* for universal ISO week-numbering date, whereas
* `Y` is supposed to be used in conjunction with `w` and `e`
* for week-numbering date specific to the locale.
* - `P` is long localized date format
* - `p` is long localized time format
*/
export const formatters = {
// Era
G: function (date, token, localize) {
const era = date.getFullYear() > 0 ? 1 : 0;
switch (token) {
// AD, BC
case "G":
case "GG":
case "GGG":
return localize.era(era, { width: "abbreviated" });
// A, B
case "GGGGG":
return localize.era(era, { width: "narrow" });
// Anno Domini, Before Christ
case "GGGG":
default:
return localize.era(era, { width: "wide" });
}
},
// Year
y: function (date, token, localize) {
// Ordinal number
if (token === "yo") {
const signedYear = date.getFullYear();
// Returns 1 for 1 BC (which is year 0 in JavaScript)
const year = signedYear > 0 ? signedYear : 1 - signedYear;
return localize.ordinalNumber(year, { unit: "year" });
}
return lightFormatters.y(date, token);
},
// Local week-numbering year
Y: function (date, token, localize, options) {
const signedWeekYear = getWeekYear(date, options);
// Returns 1 for 1 BC (which is year 0 in JavaScript)
const weekYear = signedWeekYear > 0 ? signedWeekYear : 1 - signedWeekYear;
// Two digit year
if (token === "YY") {
const twoDigitYear = weekYear % 100;
return addLeadingZeros(twoDigitYear, 2);
}
// Ordinal number
if (token === "Yo") {
return localize.ordinalNumber(weekYear, { unit: "year" });
}
// Padding
return addLeadingZeros(weekYear, token.length);
},
// ISO week-numbering year
R: function (date, token) {
const isoWeekYear = getISOWeekYear(date);
// Padding
return addLeadingZeros(isoWeekYear, token.length);
},
// Extended year. This is a single number designating the year of this calendar system.
// The main difference between `y` and `u` localizers are B.C. years:
// | Year | `y` | `u` |
// |------|-----|-----|
// | AC 1 | 1 | 1 |
// | BC 1 | 1 | 0 |
// | BC 2 | 2 | -1 |
// Also `yy` always returns the last two digits of a year,
// while `uu` pads single digit years to 2 characters and returns other years unchanged.
u: function (date, token) {
const year = date.getFullYear();
return addLeadingZeros(year, token.length);
},
// Quarter
Q: function (date, token, localize) {
const quarter = Math.ceil((date.getMonth() + 1) / 3);
switch (token) {
// 1, 2, 3, 4
case "Q":
return String(quarter);
// 01, 02, 03, 04
case "QQ":
return addLeadingZeros(quarter, 2);
// 1st, 2nd, 3rd, 4th
case "Qo":
return localize.ordinalNumber(quarter, { unit: "quarter" });
// Q1, Q2, Q3, Q4
case "QQQ":
return localize.quarter(quarter, {
width: "abbreviated",
context: "formatting",
});
// 1, 2, 3, 4 (narrow quarter; could be not numerical)
case "QQQQQ":
return localize.quarter(quarter, {
width: "narrow",
context: "formatting",
});
// 1st quarter, 2nd quarter, ...
case "QQQQ":
default:
return localize.quarter(quarter, {
width: "wide",
context: "formatting",
});
}
},
// Stand-alone quarter
q: function (date, token, localize) {
const quarter = Math.ceil((date.getMonth() + 1) / 3);
switch (token) {
// 1, 2, 3, 4
case "q":
return String(quarter);
// 01, 02, 03, 04
case "qq":
return addLeadingZeros(quarter, 2);
// 1st, 2nd, 3rd, 4th
case "qo":
return localize.ordinalNumber(quarter, { unit: "quarter" });
// Q1, Q2, Q3, Q4
case "qqq":
return localize.quarter(quarter, {
width: "abbreviated",
context: "standalone",
});
// 1, 2, 3, 4 (narrow quarter; could be not numerical)
case "qqqqq":
return localize.quarter(quarter, {
width: "narrow",
context: "standalone",
});
// 1st quarter, 2nd quarter, ...
case "qqqq":
default:
return localize.quarter(quarter, {
width: "wide",
context: "standalone",
});
}
},
// Month
M: function (date, token, localize) {
const month = date.getMonth();
switch (token) {
case "M":
case "MM":
return lightFormatters.M(date, token);
// 1st, 2nd, ..., 12th
case "Mo":
return localize.ordinalNumber(month + 1, { unit: "month" });
// Jan, Feb, ..., Dec
case "MMM":
return localize.month(month, {
width: "abbreviated",
context: "formatting",
});
// J, F, ..., D
case "MMMMM":
return localize.month(month, {
width: "narrow",
context: "formatting",
});
// January, February, ..., December
case "MMMM":
default:
return localize.month(month, { width: "wide", context: "formatting" });
}
},
// Stand-alone month
L: function (date, token, localize) {
const month = date.getMonth();
switch (token) {
// 1, 2, ..., 12
case "L":
return String(month + 1);
// 01, 02, ..., 12
case "LL":
return addLeadingZeros(month + 1, 2);
// 1st, 2nd, ..., 12th
case "Lo":
return localize.ordinalNumber(month + 1, { unit: "month" });
// Jan, Feb, ..., Dec
case "LLL":
return localize.month(month, {
width: "abbreviated",
context: "standalone",
});
// J, F, ..., D
case "LLLLL":
return localize.month(month, {
width: "narrow",
context: "standalone",
});
// January, February, ..., December
case "LLLL":
default:
return localize.month(month, { width: "wide", context: "standalone" });
}
},
// Local week of year
w: function (date, token, localize, options) {
const week = getWeek(date, options);
if (token === "wo") {
return localize.ordinalNumber(week, { unit: "week" });
}
return addLeadingZeros(week, token.length);
},
// ISO week of year
I: function (date, token, localize) {
const isoWeek = getISOWeek(date);
if (token === "Io") {
return localize.ordinalNumber(isoWeek, { unit: "week" });
}
return addLeadingZeros(isoWeek, token.length);
},
// Day of the month
d: function (date, token, localize) {
if (token === "do") {
return localize.ordinalNumber(date.getDate(), { unit: "date" });
}
return lightFormatters.d(date, token);
},
// Day of year
D: function (date, token, localize) {
const dayOfYear = getDayOfYear(date);
if (token === "Do") {
return localize.ordinalNumber(dayOfYear, { unit: "dayOfYear" });
}
return addLeadingZeros(dayOfYear, token.length);
},
// Day of week
E: function (date, token, localize) {
const dayOfWeek = date.getDay();
switch (token) {
// Tue
case "E":
case "EE":
case "EEE":
return localize.day(dayOfWeek, {
width: "abbreviated",
context: "formatting",
});
// T
case "EEEEE":
return localize.day(dayOfWeek, {
width: "narrow",
context: "formatting",
});
// Tu
case "EEEEEE":
return localize.day(dayOfWeek, {
width: "short",
context: "formatting",
});
// Tuesday
case "EEEE":
default:
return localize.day(dayOfWeek, {
width: "wide",
context: "formatting",
});
}
},
// Local day of week
e: function (date, token, localize, options) {
const dayOfWeek = date.getDay();
const localDayOfWeek = (dayOfWeek - options.weekStartsOn + 8) % 7 || 7;
switch (token) {
// Numerical value (Nth day of week with current locale or weekStartsOn)
case "e":
return String(localDayOfWeek);
// Padded numerical value
case "ee":
return addLeadingZeros(localDayOfWeek, 2);
// 1st, 2nd, ..., 7th
case "eo":
return localize.ordinalNumber(localDayOfWeek, { unit: "day" });
case "eee":
return localize.day(dayOfWeek, {
width: "abbreviated",
context: "formatting",
});
// T
case "eeeee":
return localize.day(dayOfWeek, {
width: "narrow",
context: "formatting",
});
// Tu
case "eeeeee":
return localize.day(dayOfWeek, {
width: "short",
context: "formatting",
});
// Tuesday
case "eeee":
default:
return localize.day(dayOfWeek, {
width: "wide",
context: "formatting",
});
}
},
// Stand-alone local day of week
c: function (date, token, localize, options) {
const dayOfWeek = date.getDay();
const localDayOfWeek = (dayOfWeek - options.weekStartsOn + 8) % 7 || 7;
switch (token) {
// Numerical value (same as in `e`)
case "c":
return String(localDayOfWeek);
// Padded numerical value
case "cc":
return addLeadingZeros(localDayOfWeek, token.length);
// 1st, 2nd, ..., 7th
case "co":
return localize.ordinalNumber(localDayOfWeek, { unit: "day" });
case "ccc":
return localize.day(dayOfWeek, {
width: "abbreviated",
context: "standalone",
});
// T
case "ccccc":
return localize.day(dayOfWeek, {
width: "narrow",
context: "standalone",
});
// Tu
case "cccccc":
return localize.day(dayOfWeek, {
width: "short",
context: "standalone",
});
// Tuesday
case "cccc":
default:
return localize.day(dayOfWeek, {
width: "wide",
context: "standalone",
});
}
},
// ISO day of week
i: function (date, token, localize) {
const dayOfWeek = date.getDay();
const isoDayOfWeek = dayOfWeek === 0 ? 7 : dayOfWeek;
switch (token) {
// 2
case "i":
return String(isoDayOfWeek);
// 02
case "ii":
return addLeadingZeros(isoDayOfWeek, token.length);
// 2nd
case "io":
return localize.ordinalNumber(isoDayOfWeek, { unit: "day" });
// Tue
case "iii":
return localize.day(dayOfWeek, {
width: "abbreviated",
context: "formatting",
});
// T
case "iiiii":
return localize.day(dayOfWeek, {
width: "narrow",
context: "formatting",
});
// Tu
case "iiiiii":
return localize.day(dayOfWeek, {
width: "short",
context: "formatting",
});
// Tuesday
case "iiii":
default:
return localize.day(dayOfWeek, {
width: "wide",
context: "formatting",
});
}
},
// AM or PM
a: function (date, token, localize) {
const hours = date.getHours();
const dayPeriodEnumValue = hours / 12 >= 1 ? "pm" : "am";
switch (token) {
case "a":
case "aa":
return localize.dayPeriod(dayPeriodEnumValue, {
width: "abbreviated",
context: "formatting",
});
case "aaa":
return localize
.dayPeriod(dayPeriodEnumValue, {
width: "abbreviated",
context: "formatting",
})
.toLowerCase();
case "aaaaa":
return localize.dayPeriod(dayPeriodEnumValue, {
width: "narrow",
context: "formatting",
});
case "aaaa":
default:
return localize.dayPeriod(dayPeriodEnumValue, {
width: "wide",
context: "formatting",
});
}
},
// AM, PM, midnight, noon
b: function (date, token, localize) {
const hours = date.getHours();
let dayPeriodEnumValue;
if (hours === 12) {
dayPeriodEnumValue = dayPeriodEnum.noon;
} else if (hours === 0) {
dayPeriodEnumValue = dayPeriodEnum.midnight;
} else {
dayPeriodEnumValue = hours / 12 >= 1 ? "pm" : "am";
}
switch (token) {
case "b":
case "bb":
return localize.dayPeriod(dayPeriodEnumValue, {
width: "abbreviated",
context: "formatting",
});
case "bbb":
return localize
.dayPeriod(dayPeriodEnumValue, {
width: "abbreviated",
context: "formatting",
})
.toLowerCase();
case "bbbbb":
return localize.dayPeriod(dayPeriodEnumValue, {
width: "narrow",
context: "formatting",
});
case "bbbb":
default:
return localize.dayPeriod(dayPeriodEnumValue, {
width: "wide",
context: "formatting",
});
}
},
// in the morning, in the afternoon, in the evening, at night
B: function (date, token, localize) {
const hours = date.getHours();
let dayPeriodEnumValue;
if (hours >= 17) {
dayPeriodEnumValue = dayPeriodEnum.evening;
} else if (hours >= 12) {
dayPeriodEnumValue = dayPeriodEnum.afternoon;
} else if (hours >= 4) {
dayPeriodEnumValue = dayPeriodEnum.morning;
} else {
dayPeriodEnumValue = dayPeriodEnum.night;
}
switch (token) {
case "B":
case "BB":
case "BBB":
return localize.dayPeriod(dayPeriodEnumValue, {
width: "abbreviated",
context: "formatting",
});
case "BBBBB":
return localize.dayPeriod(dayPeriodEnumValue, {
width: "narrow",
context: "formatting",
});
case "BBBB":
default:
return localize.dayPeriod(dayPeriodEnumValue, {
width: "wide",
context: "formatting",
});
}
},
// Hour [1-12]
h: function (date, token, localize) {
if (token === "ho") {
let hours = date.getHours() % 12;
if (hours === 0) hours = 12;
return localize.ordinalNumber(hours, { unit: "hour" });
}
return lightFormatters.h(date, token);
},
// Hour [0-23]
H: function (date, token, localize) {
if (token === "Ho") {
return localize.ordinalNumber(date.getHours(), { unit: "hour" });
}
return lightFormatters.H(date, token);
},
// Hour [0-11]
K: function (date, token, localize) {
const hours = date.getHours() % 12;
if (token === "Ko") {
return localize.ordinalNumber(hours, { unit: "hour" });
}
return addLeadingZeros(hours, token.length);
},
// Hour [1-24]
k: function (date, token, localize) {
let hours = date.getHours();
if (hours === 0) hours = 24;
if (token === "ko") {
return localize.ordinalNumber(hours, { unit: "hour" });
}
return addLeadingZeros(hours, token.length);
},
// Minute
m: function (date, token, localize) {
if (token === "mo") {
return localize.ordinalNumber(date.getMinutes(), { unit: "minute" });
}
return lightFormatters.m(date, token);
},
// Second
s: function (date, token, localize) {
if (token === "so") {
return localize.ordinalNumber(date.getSeconds(), { unit: "second" });
}
return lightFormatters.s(date, token);
},
// Fraction of second
S: function (date, token) {
return lightFormatters.S(date, token);
},
// Timezone (ISO-8601. If offset is 0, output is always `'Z'`)
X: function (date, token, _localize) {
const timezoneOffset = date.getTimezoneOffset();
if (timezoneOffset === 0) {
return "Z";
}
switch (token) {
// Hours and optional minutes
case "X":
return formatTimezoneWithOptionalMinutes(timezoneOffset);
// Hours, minutes and optional seconds without `:` delimiter
// Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets
// so this token always has the same output as `XX`
case "XXXX":
case "XX": // Hours and minutes without `:` delimiter
return formatTimezone(timezoneOffset);
// Hours, minutes and optional seconds with `:` delimiter
// Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets
// so this token always has the same output as `XXX`
case "XXXXX":
case "XXX": // Hours and minutes with `:` delimiter
default:
return formatTimezone(timezoneOffset, ":");
}
},
// Timezone (ISO-8601. If offset is 0, output is `'+00:00'` or equivalent)
x: function (date, token, _localize) {
const timezoneOffset = date.getTimezoneOffset();
switch (token) {
// Hours and optional minutes
case "x":
return formatTimezoneWithOptionalMinutes(timezoneOffset);
// Hours, minutes and optional seconds without `:` delimiter
// Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets
// so this token always has the same output as `xx`
case "xxxx":
case "xx": // Hours and minutes without `:` delimiter
return formatTimezone(timezoneOffset);
// Hours, minutes and optional seconds with `:` delimiter
// Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets
// so this token always has the same output as `xxx`
case "xxxxx":
case "xxx": // Hours and minutes with `:` delimiter
default:
return formatTimezone(timezoneOffset, ":");
}
},
// Timezone (GMT)
O: function (date, token, _localize) {
const timezoneOffset = date.getTimezoneOffset();
switch (token) {
// Short
case "O":
case "OO":
case "OOO":
return "GMT" + formatTimezoneShort(timezoneOffset, ":");
// Long
case "OOOO":
default:
return "GMT" + formatTimezone(timezoneOffset, ":");
}
},
// Timezone (specific non-location)
z: function (date, token, _localize) {
const timezoneOffset = date.getTimezoneOffset();
switch (token) {
// Short
case "z":
case "zz":
case "zzz":
return "GMT" + formatTimezoneShort(timezoneOffset, ":");
// Long
case "zzzz":
default:
return "GMT" + formatTimezone(timezoneOffset, ":");
}
},
// Seconds timestamp
t: function (date, token, _localize) {
const timestamp = Math.trunc(+date / 1000);
return addLeadingZeros(timestamp, token.length);
},
// Milliseconds timestamp
T: function (date, token, _localize) {
return addLeadingZeros(+date, token.length);
},
};
function formatTimezoneShort(offset, delimiter = "") {
const sign = offset > 0 ? "-" : "+";
const absOffset = Math.abs(offset);
const hours = Math.trunc(absOffset / 60);
const minutes = absOffset % 60;
if (minutes === 0) {
return sign + String(hours);
}
return sign + String(hours) + delimiter + addLeadingZeros(minutes, 2);
}
function formatTimezoneWithOptionalMinutes(offset, delimiter) {
if (offset % 60 === 0) {
const sign = offset > 0 ? "-" : "+";
return sign + addLeadingZeros(Math.abs(offset) / 60, 2);
}
return formatTimezone(offset, delimiter);
}
function formatTimezone(offset, delimiter = "") {
const sign = offset > 0 ? "-" : "+";
const absOffset = Math.abs(offset);
const hours = addLeadingZeros(Math.trunc(absOffset / 60), 2);
const minutes = addLeadingZeros(absOffset % 60, 2);
return sign + hours + delimiter + minutes;
}

Some files were not shown because too many files have changed in this diff Show More