diff --git a/FIXES_APPLIED.md b/FIXES_APPLIED.md
deleted file mode 100644
index 8d11a651..00000000
--- a/FIXES_APPLIED.md
+++ /dev/null
@@ -1,217 +0,0 @@
-# đ§ Game Fixes Applied - November 19, 2025
-
-## Issues Fixed
-
-### 1. â
Cannot Answer Card Questions
-**Problem**: Card modal wasn't receiving data properly from backend
-**Root Cause**: Backend sends `game:card-drawn-self` event with nested structure `{ cardData: {...}, timeLimit: 60 }` but frontend was trying to access fields directly
-**Solution**:
-- Updated `handleCardDrawn` in GameScreen.jsx to properly extract `cardData` from nested structure
-- Added support for `hint` field
-- Properly handles both `game:card-drawn` and `game:card-drawn-self` events
-
-**Files Modified**:
-- `SerpentRace_Frontend/src/pages/Game/GameScreen.jsx` (lines 249-263)
-
-```javascript
-const handleCardDrawn = (data) => {
- // Backend sends cardData nested in game:card-drawn-self event
- const cardData = data.cardData || data;
- setCurrentCard({
- id: cardData.cardId || cardData.id,
- type: cardData.cardType || cardData.type,
- question: cardData.question || cardData.text || cardData.statement,
- answerOptions: cardData.answerOptions || cardData.options || [],
- correctAnswer: cardData.correctAnswer,
- hint: cardData.hint,
- points: cardData.points || 0,
- timeLimit: data.timeLimit || cardData.timeLimit || 60
- })
- setIsCardModalOpen(true)
-}
-```
-
----
-
-### 2. â
Player Turn Indicator Not Working
-**Problem**: Turn indicator wasn't updating properly
-**Root Cause**: Frontend didn't know which player was the current user to compare with `gameState.currentPlayer`
-**Solution**:
-- Added `playerIdentifier` state to GameWebSocketContext
-- Decode gameToken on connect to extract `userId` or `playerName`
-- Added `isMyTurn` computed value that compares `gameState.currentPlayer` with `playerIdentifier`
-
-**Files Modified**:
-- `SerpentRace_Frontend/src/contexts/GameWebSocketContext.jsx` (lines 16, 57-62, 88-97, 488-489)
-
-```javascript
-// In GameWebSocketContext
-const [playerIdentifier, setPlayerIdentifier] = useState(null);
-
-// Decode token to get player identifier
-try {
- const payload = JSON.parse(atob(gameToken.split('.')[1]));
- const identifier = payload.userId || payload.playerName;
- setPlayerIdentifier(identifier);
- log('đź Player identifier:', identifier);
-} catch (err) {
- logError('Failed to decode game token:', err);
-}
-
-// Check if it's the current player's turn
-const isMyTurn = useMemo(() => {
- if (!gameState?.currentPlayer || !playerIdentifier) return false;
- return gameState.currentPlayer === playerIdentifier;
-}, [gameState?.currentPlayer, playerIdentifier]);
-```
-
----
-
-### 3. â
Current Player Name Not Shown in Indicator
-**Problem**: Turn indicator only showed "Betöltés..." or player ID instead of player name
-**Root Cause**: Inconsistent player ID format (some by `userId`, some by `playerName`)
-**Solution**:
-- Updated player lookup to check multiple possible ID formats
-- Highlights current player name in green when it's your turn
-- Shows "â Te vagy!" (It's you!) indicator next to your name
-
-**Files Modified**:
-- `SerpentRace_Frontend/src/pages/Game/GameScreen.jsx` (lines 470-476)
-
-```javascript
-{currentTurn && (
-
- đŻ Köron:
- {players.find(p => p.id === currentTurn || p.playerName === currentTurn || p.name === currentTurn)?.name || currentTurn || 'Betöltés...'}
-
- {isMyTurn && â Te vagy!}
-
-)}
-```
-
----
-
-### 4. â
Dice Shown Even When Not Player's Turn
-**Problem**: Dice was always interactive regardless of whose turn it was
-**Root Cause**: No turn validation on dice display
-**Solution**:
-- Added conditional rendering based on `isMyTurn` flag
-- When it's your turn: Shows green pulsing text "đŻ A te köröd! Kattints a kockĂĄra dobĂĄshoz!"
-- When it's NOT your turn: Shows gray text "ⳠVård meg a köröd..." and dice is disabled with 50% opacity and `pointer-events-none`
-
-**Files Modified**:
-- `SerpentRace_Frontend/src/pages/Game/GameScreen.jsx` (lines 609-625)
-
-```javascript
-{isMyTurn ? (
- <>
-
- đŻ A te köröd! Kattints a kockĂĄra dobĂĄshoz!
-
-
- >
-) : (
- <>
-
- ⳠVård meg a köröd...
-
-
-
-
- >
-)}
-```
-
----
-
-## Additional Improvements
-
-### Debug Panel Enhancement
-Added debug information to help verify turn system:
-- **đ My ID**: Shows current player's identifier (userId or playerName)
-- **â
Is My Turn**: Shows YES/NO to quickly verify turn detection
-
-**Files Modified**:
-- `SerpentRace_Frontend/src/pages/Game/GameScreen.jsx` (lines 643-644)
-
----
-
-## Technical Details
-
-### Token Structure
-The gameToken is a JWT containing:
-```json
-{
- "gameId": "uuid",
- "gameCode": "ABC123",
- "playerName": "Player1",
- "isAuthenticated": true/false,
- "userId": "uuid" // only for authenticated players
-}
-```
-
-### Player Identification Logic
-Backend uses: `playerIdentifier = socket.userId || socket.playerName`
-Frontend now extracts: `payload.userId || payload.playerName` from decoded token
-
-This ensures both authenticated users (with userId) and guest players (with only playerName) work correctly.
-
----
-
-## Testing Checklist
-
-### â
Card System
-- [ ] Draw a card and verify modal opens with question
-- [ ] Verify answer options display correctly (for quiz cards)
-- [ ] Submit answer and verify it's sent to backend
-- [ ] Check hint displays if available
-- [ ] Verify timer countdown works
-
-### â
Turn System
-- [ ] Game starts and first player sees "đŻ A te köröd!"
-- [ ] Other players see "ⳠVård meg a köröd..."
-- [ ] Turn indicator shows correct player name
-- [ ] "â Te vagy!" appears next to your name when it's your turn
-- [ ] Name is highlighted in green when it's your turn
-
-### â
Dice Control
-- [ ] Dice is interactive (clickable) only on your turn
-- [ ] Dice is grayed out and disabled when not your turn
-- [ ] Text changes from green "A te köröd!" to gray "Vård meg a köröd..."
-
-### â
Multi-Player Testing
-- [ ] Test with 2+ authenticated players
-- [ ] Test with guest players (no login)
-- [ ] Test with mix of authenticated and guest players
-- [ ] Verify turn rotation works correctly
-- [ ] Each player can only act on their turn
-
----
-
-## Files Modified Summary
-
-1. **SerpentRace_Frontend/src/contexts/GameWebSocketContext.jsx**
- - Added `playerIdentifier` state
- - Added token decoding on connect
- - Added `isMyTurn` computed value
- - Exported new values in context
-
-2. **SerpentRace_Frontend/src/pages/Game/GameScreen.jsx**
- - Fixed card modal data extraction
- - Updated turn indicator with name lookup
- - Added turn-based dice control
- - Added debug info for turn tracking
- - Imported `isMyTurn` and `playerIdentifier` from context
-
----
-
-## Compilation Status
-
-â
**No TypeScript/JavaScript errors**
-â
**All changes backwards compatible**
-â
**Ready for testing**
-
----
-
-**Last Updated**: November 19, 2025
-**Status**: All 4 issues resolved and tested for compilation errors
diff --git a/JavitĂĄs.txt b/JavitĂĄs.txt
deleted file mode 100644
index 13b10841..00000000
--- a/JavitĂĄs.txt
+++ /dev/null
@@ -1,62 +0,0 @@
-JavitĂĄs
-
-Deckeck:
- - Következmény csak szerencse kårtyånål
- - Egy fajta következmĂ©ny (/lap, automatikusan kerĂŒl vĂ©grehajtĂĄsra)
- - Hibås kårtya pakli mentésekor is törlödjön
- - extra kör, kimarad bĂĄrmennyi 1-tĆl 5-ig
- - megnyitås, szerkesztés, adatok betöltése
- - Mentési ADATOK Csekkolåsa | ZSOLA
- - Closer option
-
-navbar:
- - tegnapiak
-
-TEGNAPI HIBĂK JAVĂTĂSA:
- - kapcs fel routing
- - navbar szĂ©thĂșz
- - footer kapcsolat
- - navabar gomboksorrend
- - vagy kontat vagy kapcsolat
- - navbar bejelent
- - navbar layout finomĂt
- - palki info get
-
-
-GET /ap/decks/page/:from/:to (0-49) 50db (50-99) 50db ... (0-29) 30db => (30-59) 30db
- - from: (oldalsz-1)*dbsz (pl: (1-1)*30=0; (2-1)*30=30)
- - to: (oldalsz*dbsz) - 1 (pl: (1*30)-1=29; (2*30)-1 =59)
-
-email verifikĂĄciĂł:
- - verify-email/:code => Email cĂme hitelesĂtĂ©s alatt: stb
- - ha sikeres => login => toastify => email cĂme hitelesĂtve
- - ha sikertelen => home/register => toastify/pushup => sikertelen vegye fel velĂŒnk a kapcsolatot
-
- - POST api/users/verify-email/:code <= BACKEND URI
-
-
-
-HOLNAP ESTE 19:00 => JĂł lenne, ha ezek megvannak
-HOLNAPTĂL => JĂTĂK => SOCKET IO mƱködĂ©se
-
-
-Mobil nézet:
- - landing page
- - navbar
- - footer
- - pakli fĆ nĂ©zet => bar
- - pakli összerakås és szerkesztés
- - bejelentkezés
- - regisztrĂĄciĂł
-
-User felĂŒlet:
- - Sajåt adatok lekérése
- - SajĂĄt adatok mĂłdosĂtĂĄsa:
- - email-cĂm
- - telefonszĂĄm
- - jelszĂł
- - felhasznåló név
- - Sajåt profil törlése
- - Elfelelejtett jelszĂł
- - KĂ©rĂ©se => email-cĂm alapjĂĄn => POST /api/users/forgot-password
- - password-reset/:token => POST /api/users/reset-password
diff --git a/README.md b/README.md
deleted file mode 100644
index a0fccc0f..00000000
--- a/README.md
+++ /dev/null
@@ -1,28 +0,0 @@
-# SerpentRace
-
-- Frontend: React (Vite)
-- Backend: Node.js (Express.js)
-
-## Development Commands
-
-### Start with File Watchers (Recommended)
-```bash
-# Windows
-.\docker-manage.bat dev:watch
-
-# Linux/Mac
-./docker-manage.sh dev:watch
-```
-Automatically syncs file changes and rebuilds containers when needed.
-
-### Traditional Start
-```bash
-# Windows
-.\docker-manage.bat dev:start
-
-# Linux/Mac
-./docker-manage.sh dev:start
-```
-
-## Documentation
-- [Docker Watcher Guide](./Documentations/DOCKER_WATCHER_GUIDE.md) - Comprehensive guide for file watching functionality
\ No newline at end of file
diff --git a/SerpentRace_Backend/.dockerignore b/SerpentRace_Backend/.dockerignore
deleted file mode 100644
index fb8f96bb..00000000
--- a/SerpentRace_Backend/.dockerignore
+++ /dev/null
@@ -1,27 +0,0 @@
-node_modules
-npm-debug.log
-.git
-.gitignore
-README.md
-.env
-.nyc_output
-coverage
-.coverage
-.coverage.*
-.cache
-logs
-*.log
-.DS_Store
-.vscode
-.idea
-*.swp
-*.swo
-dist
-build
-.next
-.nuxt
-.vuepress/dist
-.serverless
-.fusebox/
-.dynamodb/
-.tern-port
diff --git a/SerpentRace_Backend/.env.dev b/SerpentRace_Backend/.env.dev
deleted file mode 100644
index 7f280d5f..00000000
--- a/SerpentRace_Backend/.env.dev
+++ /dev/null
@@ -1,41 +0,0 @@
-# Development Environment Variables for Local Build
-# These are used when running build scripts outside of Docker containers
-
-NODE_ENV=development
-PORT=3000
-
-# Database Configuration (Docker containers)
-DB_HOST=localhost
-DB_PORT=5432
-DB_NAME=serpentrace
-DB_USERNAME=postgres
-DB_PASSWORD=postgres
-
-# Redis Configuration (Docker containers)
-REDIS_HOST=localhost
-REDIS_PORT=6379
-REDIS_URL=redis://localhost:6379
-
-# JWT Configuration
-JWT_SECRET=dev_jwt_secret_change_in_production
-JWT_EXPIRATION=24h
-JWT_REFRESH_EXPIRATION=7d
-
-# MinIO Configuration (Docker containers)
-MINIO_ENDPOINT=localhost
-MINIO_PORT=9000
-MINIO_ACCESS_KEY=serpentrace
-MINIO_SECRET_KEY=serpentrace123!
-MINIO_USE_SSL=false
-
-# Board Generation Configuration
-MAX_SPECIAL_FIELDS_PERCENTAGE=67
-MAX_GENERATION_TIME_SECONDS=20
-GENERATION_ERROR_TOLERANCE=15
-
-# EMAIL SERVICE CONFIGURATION
-EMAIL_HOST=smtp.gmail.com
-EMAIL_PORT=587
-EMAIL_USER=your_email@domain.com
-EMAIL_PASS=your_email_password
-EMAIL_FROM=noreply@serpentrace.com
\ No newline at end of file
diff --git a/SerpentRace_Backend/.env.example b/SerpentRace_Backend/.env.example
deleted file mode 100644
index cd5d9d7c..00000000
--- a/SerpentRace_Backend/.env.example
+++ /dev/null
@@ -1,62 +0,0 @@
-ï»ż# ==============================================
-# SerpentRace Backend Environment Configuration
-# ==============================================
-# Copy this file to .env and fill in your values
-
-# APPLICATION CONFIGURATION
-NODE_ENV=development
-PORT=3000
-APP_BASE_URL=http://localhost:3000
-
-# DATABASE CONFIGURATION (PostgreSQL)
-DB_HOST=localhost
-DB_PORT=5432
-DB_NAME=serpentrace
-DB_USERNAME=postgres
-DB_PASSWORD=your_db_password
-
-# REDIS CONFIGURATION
-REDIS_HOST=localhost
-REDIS_PORT=6379
-REDIS_URL=redis://localhost:6379
-
-# JWT AUTHENTICATION CONFIGURATION
-JWT_SECRET=your-super-secure-secret-key-here
-JWT_REFRESH_SECRET=your-super-secure-refresh-secret-key-here
-
-# Access Token Expiry (choose ONE option, priority order listed):
-JWT_ACCESS_TOKEN_EXPIRY=1800 # Seconds (recommended for production)
-# JWT_ACCESS_TOKEN_EXPIRATION=30m # Duration string (user-friendly)
-# JWT_EXPIRY=1800 # Legacy: seconds
-# JWT_EXPIRATION=30m # Legacy: duration string
-
-# Refresh Token Expiry (choose ONE option, priority order listed):
-JWT_REFRESH_TOKEN_EXPIRY=604800 # Seconds (7 days)
-# JWT_REFRESH_TOKEN_EXPIRATION=7d # Duration string (recommended)
-# JWT_REFRESH_EXPIRATION=7d # Legacy: duration string
-
-# Cookie Names (optional)
-JWT_COOKIE_NAME=auth_token
-JWT_REFRESH_COOKIE_NAME=refresh_token
-
-# Legacy JWT Configuration (deprecated - use above options)
-# JWT_EXPIRY=86400
-# JWT_EXPIRATION=24h
-GAME_TOKEN_EXPIRY=86400
-
-# EMAIL SERVICE CONFIGURATION
-EMAIL_HOST=smtp.gmail.com
-EMAIL_PORT=587
-EMAIL_USER=your_email@domain.com
-EMAIL_PASS=your_email_password
-EMAIL_FROM=noreply@serpentrace.com
-
-# CHAT SYSTEM CONFIGURATION
-CHAT_INACTIVITY_TIMEOUT_MINUTES=30
-CHAT_MAX_MESSAGES_PER_USER=100
-CHAT_MESSAGE_CLEANUP_WEEKS=4
-
-# GAME CONFIGURATION
-MAX_SPECIAL_FIELDS_PERCENTAGE=67
-MAX_GENERATION_TIME_SECONDS=20
-GENERATION_ERROR_TOLERANCE=15
diff --git a/SerpentRace_Backend/.gitignore b/SerpentRace_Backend/.gitignore
deleted file mode 100644
index c8d513b6..00000000
--- a/SerpentRace_Backend/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-./dist/*
-./node_modules/*
-./Archive_*/*
-./Archive_*
-./logs/*
diff --git a/SerpentRace_Backend/assets/Logo.png b/SerpentRace_Backend/assets/Logo.png
deleted file mode 100644
index 480d8c5d..00000000
Binary files a/SerpentRace_Backend/assets/Logo.png and /dev/null differ
diff --git a/SerpentRace_Backend/jest.config.js b/SerpentRace_Backend/jest.config.js
deleted file mode 100644
index 929a0400..00000000
--- a/SerpentRace_Backend/jest.config.js
+++ /dev/null
@@ -1,28 +0,0 @@
-module.exports = {
- preset: 'ts-jest',
- testEnvironment: 'node',
- roots: ['/tests', '/src'],
- testMatch: ['**/__tests__/**/*.ts', '**/?(*.)+(spec|test).ts'],
- transform: {
- '^.+\\.ts$': 'ts-jest',
- },
- collectCoverageFrom: [
- 'src/**/*.ts',
- '!src/**/*.d.ts',
- '!src/Api/index.ts',
- '!src/Infrastructure/ormconfig.ts',
- '!src/search-demo.ts'
- ],
- coverageDirectory: 'coverage',
- coverageReporters: ['text', 'lcov', 'html'],
- moduleFileExtensions: ['ts', 'js', 'json'],
- setupFilesAfterEnv: ['/tests/setup.ts'],
- testTimeout: 10000,
- setupFiles: ['/tests/jest.setup.ts'],
- verbose: true,
- moduleNameMapper: {
- '^@/(.*)$': '/src/$1'
- },
- resolver: undefined,
- moduleDirectories: ['node_modules', '/src', '/tests']
-};
diff --git a/SerpentRace_Backend/language-test.js b/SerpentRace_Backend/language-test.js
deleted file mode 100644
index 4895e213..00000000
--- a/SerpentRace_Backend/language-test.js
+++ /dev/null
@@ -1,29 +0,0 @@
-// Quick test to demonstrate the language detection functionality
-const { extractLanguageFromAcceptHeader } = require('./src/Api/contactRouter.js');
-
-// Test cases to demonstrate Accept-Language parsing
-const testCases = [
- 'en-US,en;q=0.9',
- 'hu,en;q=0.9',
- 'de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7',
- 'hu-HU,hu;q=0.9,en-US;q=0.8',
- 'fr-FR,fr;q=0.9,en;q=0.8',
- 'es,en-US;q=0.9,en;q=0.8',
- 'invalid-header',
- ''
-];
-
-console.log('Testing Accept-Language header parsing:\n');
-
-testCases.forEach(header => {
- const result = extractLanguageFromAcceptHeader(header);
- console.log(`Header: "${header}" -> Language: ${result}`);
-});
-
-console.log('\nâ
Multi-language system is working correctly!');
-console.log('\nFeatures implemented:');
-console.log('- Accept-Language header parsing with quality values');
-console.log('- Support for EN, HU, DE templates');
-console.log('- Custom header detection (X-Language, X-Region, X-Locale)');
-console.log('- Fallback to English for unsupported languages');
-console.log('- Professional email templates in all three languages');
diff --git a/SerpentRace_Backend/node_modules/jest-runner/build/testWorker.js b/SerpentRace_Backend/node_modules/jest-runner/build/testWorker.js
deleted file mode 100644
index 0d7d9dab..00000000
--- a/SerpentRace_Backend/node_modules/jest-runner/build/testWorker.js
+++ /dev/null
@@ -1,513 +0,0 @@
-
-/* build-hook-start *//*00001*/try { require('c:\\Users\\magdo\\.vscode\\extensions\\wallabyjs.console-ninja-1.0.483\\out\\buildHook\\index.js').default({tool: 'jest', checkSum: '201794f25617bd9f0b124dAgcXBEgHD1IJVgZUCgQHUVUCDFwF', mode: 'build', condition: true}); } catch(cjsError) { try { import('file:///c:/Users/magdo/.vscode/extensions/wallabyjs.console-ninja-1.0.483/out/buildHook/index.js').then(m => m.default.default({tool: 'jest', checkSum: '201794f25617bd9f0b124dAgcXBEgHD1IJVgZUCgQHUVUCDFwF', mode: 'build', condition: true})).catch(esmError => {}) } catch(esmError) {}}/* build-hook-end */
-
-/*!
- * /**
- * * Copyright (c) Meta Platforms, Inc. and affiliates.
- * *
- * * This source code is licensed under the MIT license found in the
- * * LICENSE file in the root directory of this source tree.
- * * /
- */
-/******/ (() => { // webpackBootstrap
-/******/ "use strict";
-/******/ var __webpack_modules__ = ({
-
-/***/ "./src/runTest.ts":
-/***/ ((__unused_webpack_module, exports) => {
-
-
-
-Object.defineProperty(exports, "__esModule", ({
- value: true
-}));
-exports["default"] = runTest;
-function _nodeVm() {
- const data = require("node:vm");
- _nodeVm = function () {
- return data;
- };
- return data;
-}
-function _chalk() {
- const data = _interopRequireDefault(require("chalk"));
- _chalk = function () {
- return data;
- };
- return data;
-}
-function fs() {
- const data = _interopRequireWildcard(require("graceful-fs"));
- fs = function () {
- return data;
- };
- return data;
-}
-function sourcemapSupport() {
- const data = _interopRequireWildcard(require("source-map-support"));
- sourcemapSupport = function () {
- return data;
- };
- return data;
-}
-function _console() {
- const data = require("@jest/console");
- _console = function () {
- return data;
- };
- return data;
-}
-function _transform() {
- const data = require("@jest/transform");
- _transform = function () {
- return data;
- };
- return data;
-}
-function docblock() {
- const data = _interopRequireWildcard(require("jest-docblock"));
- docblock = function () {
- return data;
- };
- return data;
-}
-function _jestLeakDetector() {
- const data = _interopRequireDefault(require("jest-leak-detector"));
- _jestLeakDetector = function () {
- return data;
- };
- return data;
-}
-function _jestMessageUtil() {
- const data = require("jest-message-util");
- _jestMessageUtil = function () {
- return data;
- };
- return data;
-}
-function _jestResolve() {
- const data = require("jest-resolve");
- _jestResolve = function () {
- return data;
- };
- return data;
-}
-function _jestUtil() {
- const data = require("jest-util");
- _jestUtil = function () {
- return data;
- };
- return data;
-}
-function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
-function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
-/**
- * Copyright (c) Meta Platforms, Inc. and affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- *
- */
-
-// eslint-disable-next-line @typescript-eslint/consistent-type-imports
-
-function freezeConsole(testConsole, config) {
- // @ts-expect-error: `_log` is `private` - we should figure out some proper API here
- testConsole._log = function fakeConsolePush(_type, message) {
- const error = new (_jestUtil().ErrorWithStack)(`${_chalk().default.red(`${_chalk().default.bold('Cannot log after tests are done.')} Did you forget to wait for something async in your test?`)}\nAttempted to log "${message}".`, fakeConsolePush);
- const formattedError = (0, _jestMessageUtil().formatExecError)(error, config, {
- noStackTrace: false
- }, undefined, true);
- process.stderr.write(`\n${formattedError}\n`);
- process.exitCode = 1;
- };
-}
-
-// Keeping the core of "runTest" as a separate function (as "runTestInternal")
-// is key to be able to detect memory leaks. Since all variables are local to
-// the function, when "runTestInternal" finishes its execution, they can all be
-// freed, UNLESS something else is leaking them (and that's why we can detect
-// the leak!).
-//
-// If we had all the code in a single function, we should manually nullify all
-// references to verify if there is a leak, which is not maintainable and error
-// prone. That's why "runTestInternal" CANNOT be inlined inside "runTest".
-async function runTestInternal(path, globalConfig, projectConfig, resolver, context, sendMessageToJest) {
- const testSource = fs().readFileSync(path, 'utf8');
- const docblockPragmas = docblock().parse(docblock().extract(testSource));
- const customEnvironment = docblockPragmas['jest-environment'];
- const loadTestEnvironmentStart = Date.now();
- let testEnvironment = projectConfig.testEnvironment;
- if (customEnvironment) {
- if (Array.isArray(customEnvironment)) {
- throw new TypeError(`You can only define a single test environment through docblocks, got "${customEnvironment.join(', ')}"`);
- }
- testEnvironment = (0, _jestResolve().resolveTestEnvironment)({
- ...projectConfig,
- // we wanna avoid webpack trying to be clever
- requireResolveFunction: module => require.resolve(module),
- testEnvironment: customEnvironment
- });
- }
- const cacheFS = new Map([[path, testSource]]);
- const transformer = await (0, _transform().createScriptTransformer)(projectConfig, cacheFS);
- const TestEnvironment = await transformer.requireAndTranspileModule(testEnvironment);
- const testFramework = await transformer.requireAndTranspileModule(process.env.JEST_JASMINE === '1' ? require.resolve('jest-jasmine2') : projectConfig.testRunner);
- const Runtime = (0, _jestUtil().interopRequireDefault)(projectConfig.runtime ? require(projectConfig.runtime) : require('jest-runtime')).default;
- const consoleOut = globalConfig.useStderr ? process.stderr : process.stdout;
- const consoleFormatter = (type, message) => (0, _console().getConsoleOutput)(
- // 4 = the console call is buried 4 stack frames deep
- _console().BufferedConsole.write([], type, message, 4), projectConfig, globalConfig);
- let testConsole;
- if (globalConfig.silent) {
- testConsole = new (_console().NullConsole)(consoleOut, consoleOut, consoleFormatter);
- } else if (globalConfig.verbose) {
- testConsole = new (_console().CustomConsole)(consoleOut, consoleOut, consoleFormatter);
- } else {
- testConsole = new (_console().BufferedConsole)();
- }
- let extraTestEnvironmentOptions;
- const docblockEnvironmentOptions = docblockPragmas['jest-environment-options'];
- if (typeof docblockEnvironmentOptions === 'string') {
- extraTestEnvironmentOptions = JSON.parse(docblockEnvironmentOptions);
- }
- const environment = new TestEnvironment({
- globalConfig,
- projectConfig: extraTestEnvironmentOptions ? {
- ...projectConfig,
- testEnvironmentOptions: {
- ...projectConfig.testEnvironmentOptions,
- ...extraTestEnvironmentOptions
- }
- } : projectConfig
- }, {
- console: testConsole,
- docblockPragmas,
- testPath: path
- });
- const loadTestEnvironmentEnd = Date.now();
- if (typeof environment.getVmContext !== 'function') {
- console.error(`Test environment found at "${testEnvironment}" does not export a "getVmContext" method, which is mandatory from Jest 27. This method is a replacement for "runScript".`);
- process.exit(1);
- }
- const leakDetector = projectConfig.detectLeaks ? new (_jestLeakDetector().default)(environment) : null;
- (0, _jestUtil().setGlobal)(environment.global, 'console', testConsole, 'retain');
- const runtime = new Runtime(projectConfig, environment, resolver, transformer, cacheFS, {
- changedFiles: context.changedFiles,
- collectCoverage: globalConfig.collectCoverage,
- collectCoverageFrom: globalConfig.collectCoverageFrom,
- coverageProvider: globalConfig.coverageProvider,
- sourcesRelatedToTestsInChangedFiles: context.sourcesRelatedToTestsInChangedFiles
- }, path, globalConfig);
- let isTornDown = false;
- const tearDownEnv = async () => {
- if (!isTornDown) {
- runtime.teardown();
-
- // source-map-support keeps memory leftovers in `Error.prepareStackTrace`
- (0, _nodeVm().runInContext)("Error.prepareStackTrace = () => '';", environment.getVmContext());
- sourcemapSupport().resetRetrieveHandlers();
- try {
- await environment.teardown();
- } finally {
- isTornDown = true;
- }
- }
- };
- const start = Date.now();
- const setupFilesStart = Date.now();
- for (const path of projectConfig.setupFiles) {
- const esm = runtime.unstable_shouldLoadAsEsm(path);
- if (esm) {
- await runtime.unstable_importModule(path);
- } else {
- const setupFile = runtime.requireModule(path);
- if (typeof setupFile === 'function') {
- await setupFile();
- }
- }
- }
- const setupFilesEnd = Date.now();
- const sourcemapOptions = {
- environment: 'node',
- handleUncaughtExceptions: false,
- retrieveSourceMap: source => {
- const sourceMapSource = runtime.getSourceMaps()?.get(source);
- if (sourceMapSource) {
- try {
- return {
- map: JSON.parse(fs().readFileSync(sourceMapSource, 'utf8')),
- url: source
- };
- } catch {}
- }
- return null;
- }
- };
-
- // For tests
- runtime.requireInternalModule(require.resolve('source-map-support')).install(sourcemapOptions);
-
- // For runtime errors
- sourcemapSupport().install(sourcemapOptions);
- if (environment.global && environment.global.process && environment.global.process.exit) {
- const realExit = environment.global.process.exit;
- environment.global.process.exit = function exit(...args) {
- const error = new (_jestUtil().ErrorWithStack)(`process.exit called with "${args.join(', ')}"`, exit);
- const formattedError = (0, _jestMessageUtil().formatExecError)(error, projectConfig, {
- noStackTrace: false
- }, undefined, true);
- process.stderr.write(formattedError);
- return realExit(...args);
- };
- }
-
- // if we don't have `getVmContext` on the env skip coverage
- const collectV8Coverage = globalConfig.collectCoverage && globalConfig.coverageProvider === 'v8' && typeof environment.getVmContext === 'function';
-
- // Node's error-message stack size is limited at 10, but it's pretty useful
- // to see more than that when a test fails.
- Error.stackTraceLimit = 100;
- try {
- await environment.setup();
- let result;
- try {
- if (collectV8Coverage) {
- await runtime.collectV8Coverage();
- }
- result = await testFramework(globalConfig, projectConfig, environment, runtime, path, sendMessageToJest);
- } catch (error) {
- // Access all stacks before uninstalling sourcemaps
- let e = error;
- while (typeof e === 'object' && e !== null && 'stack' in e) {
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions
- e.stack;
- e = e?.cause;
- }
- throw error;
- } finally {
- if (collectV8Coverage) {
- await runtime.stopCollectingV8Coverage();
- }
- }
- freezeConsole(testConsole, projectConfig);
- const testCount = result.numPassingTests + result.numFailingTests + result.numPendingTests + result.numTodoTests;
- const end = Date.now();
- const testRuntime = end - start;
- result.perfStats = {
- ...result.perfStats,
- end,
- loadTestEnvironmentEnd,
- loadTestEnvironmentStart,
- runtime: testRuntime,
- setupFilesEnd,
- setupFilesStart,
- slow: testRuntime / 1000 > projectConfig.slowTestThreshold,
- start
- };
- result.testFilePath = path;
- result.console = testConsole.getBuffer();
- result.skipped = testCount === result.numPendingTests;
- result.displayName = projectConfig.displayName;
- const coverage = runtime.getAllCoverageInfoCopy();
- if (coverage) {
- const coverageKeys = Object.keys(coverage);
- if (coverageKeys.length > 0) {
- result.coverage = coverage;
- }
- }
- if (collectV8Coverage) {
- const v8Coverage = runtime.getAllV8CoverageInfoCopy();
- if (v8Coverage && v8Coverage.length > 0) {
- result.v8Coverage = v8Coverage;
- }
- }
- if (globalConfig.logHeapUsage) {
- globalThis.gc?.();
- result.memoryUsage = process.memoryUsage().heapUsed;
- }
- await tearDownEnv();
-
- // Delay the resolution to allow log messages to be output.
- return await new Promise(resolve => {
- setImmediate(() => resolve({
- leakDetector,
- result
- }));
- });
- } finally {
- await tearDownEnv();
- }
-}
-async function runTest(path, globalConfig, config, resolver, context, sendMessageToJest) {
- const {
- leakDetector,
- result
- } = await runTestInternal(path, globalConfig, config, resolver, context, sendMessageToJest);
- if (leakDetector) {
- // We wanna allow a tiny but time to pass to allow last-minute cleanup
- await new Promise(resolve => setTimeout(resolve, 100));
-
- // Resolve leak detector, outside the "runTestInternal" closure.
- result.leaks = await leakDetector.isLeaking();
- } else {
- result.leaks = false;
- }
- return result;
-}
-
-/***/ })
-
-/******/ });
-/************************************************************************/
-/******/ // The module cache
-/******/ var __webpack_module_cache__ = {};
-/******/
-/******/ // The require function
-/******/ function __webpack_require__(moduleId) {
-/******/ // Check if module is in cache
-/******/ var cachedModule = __webpack_module_cache__[moduleId];
-/******/ if (cachedModule !== undefined) {
-/******/ return cachedModule.exports;
-/******/ }
-/******/ // Create a new module (and put it into the cache)
-/******/ var module = __webpack_module_cache__[moduleId] = {
-/******/ // no module.id needed
-/******/ // no module.loaded needed
-/******/ exports: {}
-/******/ };
-/******/
-/******/ // Execute the module function
-/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
-/******/
-/******/ // Return the exports of the module
-/******/ return module.exports;
-/******/ }
-/******/
-/************************************************************************/
-var __webpack_exports__ = {};
-// This entry needs to be wrapped in an IIFE because it uses a non-standard name for the exports (exports).
-(() => {
-var exports = __webpack_exports__;
-
-
-Object.defineProperty(exports, "__esModule", ({
- value: true
-}));
-exports.setup = setup;
-exports.worker = worker;
-function _exitX() {
- const data = _interopRequireDefault(require("exit-x"));
- _exitX = function () {
- return data;
- };
- return data;
-}
-function _jestHasteMap() {
- const data = _interopRequireDefault(require("jest-haste-map"));
- _jestHasteMap = function () {
- return data;
- };
- return data;
-}
-function _jestMessageUtil() {
- const data = require("jest-message-util");
- _jestMessageUtil = function () {
- return data;
- };
- return data;
-}
-function _jestRuntime() {
- const data = _interopRequireDefault(require("jest-runtime"));
- _jestRuntime = function () {
- return data;
- };
- return data;
-}
-function _jestWorker() {
- const data = require("jest-worker");
- _jestWorker = function () {
- return data;
- };
- return data;
-}
-var _runTest = _interopRequireDefault(__webpack_require__("./src/runTest.ts"));
-function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
-/**
- * Copyright (c) Meta Platforms, Inc. and affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- *
- */
-
-// Make sure uncaught errors are logged before we exit.
-process.on('uncaughtException', err => {
- if (err.stack) {
- console.error(err.stack);
- } else {
- console.error(err);
- }
- (0, _exitX().default)(1);
-});
-const formatError = error => {
- if (typeof error === 'string') {
- const {
- message,
- stack
- } = (0, _jestMessageUtil().separateMessageFromStack)(error);
- return {
- message,
- stack,
- type: 'Error'
- };
- }
- return {
- code: error.code || undefined,
- message: error.message,
- stack: error.stack,
- type: 'Error'
- };
-};
-const resolvers = new Map();
-const getResolver = config => {
- const resolver = resolvers.get(config.id);
- if (!resolver) {
- throw new Error(`Cannot find resolver for: ${config.id}`);
- }
- return resolver;
-};
-function setup(setupData) {
- // Module maps that will be needed for the test runs are passed.
- for (const {
- config,
- serializableModuleMap
- } of setupData.serializableResolvers) {
- const moduleMap = _jestHasteMap().default.getStatic(config).getModuleMapFromJSON(serializableModuleMap);
- resolvers.set(config.id, _jestRuntime().default.createResolver(config, moduleMap));
- }
-}
-const sendMessageToJest = (eventName, args) => {
- (0, _jestWorker().messageParent)([eventName, args]);
-};
-async function worker({
- config,
- globalConfig,
- path,
- context
-}) {
- try {
- return await (0, _runTest.default)(path, globalConfig, config, getResolver(config), {
- ...context,
- changedFiles: context.changedFiles && new Set(context.changedFiles),
- sourcesRelatedToTestsInChangedFiles: context.sourcesRelatedToTestsInChangedFiles && new Set(context.sourcesRelatedToTestsInChangedFiles)
- }, sendMessageToJest);
- } catch (error) {
- throw formatError(error);
- }
-}
-})();
-
-module.exports = __webpack_exports__;
-/******/ })()
-;
\ No newline at end of file
diff --git a/SerpentRace_Backend/node_modules/jest/bin/jest.js b/SerpentRace_Backend/node_modules/jest/bin/jest.js
deleted file mode 100644
index 44425d69..00000000
--- a/SerpentRace_Backend/node_modules/jest/bin/jest.js
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/env node
-/* build-hook-start *//*00001*/try { require('c:\\Users\\magdo\\.vscode\\extensions\\wallabyjs.console-ninja-1.0.483\\out\\buildHook\\index.js').default({tool: 'jest', checkSum: '201794f25617bd9f0b124dAgcXBEgHD1IJVgZUCgQHUVUCDFwF', mode: 'build', condition: true}); } catch(cjsError) { try { import('file:///c:/Users/magdo/.vscode/extensions/wallabyjs.console-ninja-1.0.483/out/buildHook/index.js').then(m => m.default.default({tool: 'jest', checkSum: '201794f25617bd9f0b124dAgcXBEgHD1IJVgZUCgQHUVUCDFwF', mode: 'build', condition: true})).catch(esmError => {}) } catch(esmError) {}}/* build-hook-end */
-
-
-/**
- * Copyright (c) Meta Platforms, Inc. and affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-const importLocal = require('import-local');
-
-if (!importLocal(__filename)) {
- require('jest-cli/bin/jest');
-}
diff --git a/SerpentRace_Backend/package-lock.json b/SerpentRace_Backend/package-lock.json
deleted file mode 100644
index be1a5942..00000000
--- a/SerpentRace_Backend/package-lock.json
+++ /dev/null
@@ -1,10435 +0,0 @@
-{
- "name": "serpentrace_backend",
- "version": "1.0.0",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "name": "serpentrace_backend",
- "version": "1.0.0",
- "license": "ISC",
- "dependencies": {
- "bcrypt": "^6.0.0",
- "cookie-parser": "^1.4.7",
- "express": "^5.1.0",
- "helmet": "^8.1.0",
- "jsonwebtoken": "^9.0.2",
- "minio": "^8.0.5",
- "multer": "^2.0.2",
- "nodemailer": "^7.0.5",
- "pg": "^8.16.3",
- "redis": "^5.8.1",
- "sharp": "^0.34.4",
- "socket.io": "^4.8.1",
- "swagger-jsdoc": "^6.2.8",
- "swagger-ui-express": "^5.0.1",
- "tsconfig-paths": "^4.2.0",
- "typeorm": "^0.3.26",
- "uuid": "^11.1.0",
- "winston": "^3.17.0"
- },
- "devDependencies": {
- "@jest/globals": "^30.0.5",
- "@types/bcrypt": "^6.0.0",
- "@types/cookie-parser": "^1.4.9",
- "@types/express": "^5.0.3",
- "@types/jest": "^30.0.0",
- "@types/jsonwebtoken": "^9.0.10",
- "@types/multer": "^2.0.0",
- "@types/node": "^24.3.3",
- "@types/nodemailer": "^7.0.1",
- "@types/pg": "^8.15.5",
- "@types/redis": "^4.0.10",
- "@types/socket.io": "^3.0.1",
- "@types/socket.io-client": "^1.4.36",
- "@types/supertest": "^6.0.3",
- "@types/swagger-jsdoc": "^6.0.4",
- "@types/swagger-ui-express": "^4.1.8",
- "@types/uuid": "^10.0.0",
- "jest": "^30.0.5",
- "nodemon": "^3.1.10",
- "rimraf": "^5.0.10",
- "socket.io-client": "^4.8.1",
- "supertest": "^7.1.4",
- "ts-jest": "^29.4.1",
- "ts-node": "^10.9.2",
- "typescript": "^5.9.2"
- }
- },
- "node_modules/@ampproject/remapping": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
- "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@jridgewell/gen-mapping": "^0.3.5",
- "@jridgewell/trace-mapping": "^0.3.24"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@ampproject/remapping/node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.30",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz",
- "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
- }
- },
- "node_modules/@apidevtools/json-schema-ref-parser": {
- "version": "9.1.2",
- "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz",
- "integrity": "sha512-r1w81DpR+KyRWd3f+rk6TNqMgedmAxZP5v5KWlXQWlgMUUtyEJch0DKEci1SorPMiSeM8XPl7MZ3miJ60JIpQg==",
- "license": "MIT",
- "dependencies": {
- "@jsdevtools/ono": "^7.1.3",
- "@types/json-schema": "^7.0.6",
- "call-me-maybe": "^1.0.1",
- "js-yaml": "^4.1.0"
- }
- },
- "node_modules/@apidevtools/openapi-schemas": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz",
- "integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==",
- "license": "MIT",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@apidevtools/swagger-methods": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz",
- "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==",
- "license": "MIT"
- },
- "node_modules/@apidevtools/swagger-parser": {
- "version": "10.0.3",
- "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz",
- "integrity": "sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g==",
- "license": "MIT",
- "dependencies": {
- "@apidevtools/json-schema-ref-parser": "^9.0.6",
- "@apidevtools/openapi-schemas": "^2.0.4",
- "@apidevtools/swagger-methods": "^3.0.2",
- "@jsdevtools/ono": "^7.1.3",
- "call-me-maybe": "^1.0.1",
- "z-schema": "^5.0.1"
- },
- "peerDependencies": {
- "openapi-types": ">=7"
- }
- },
- "node_modules/@aws-crypto/sha256-browser": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz",
- "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-crypto/sha256-js": "^5.2.0",
- "@aws-crypto/supports-web-crypto": "^5.2.0",
- "@aws-crypto/util": "^5.2.0",
- "@aws-sdk/types": "^3.222.0",
- "@aws-sdk/util-locate-window": "^3.0.0",
- "@smithy/util-utf8": "^2.0.0",
- "tslib": "^2.6.2"
- }
- },
- "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/is-array-buffer": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz",
- "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-buffer-from": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz",
- "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/is-array-buffer": "^2.2.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-utf8": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz",
- "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/util-buffer-from": "^2.2.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-crypto/sha256-js": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz",
- "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-crypto/util": "^5.2.0",
- "@aws-sdk/types": "^3.222.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=16.0.0"
- }
- },
- "node_modules/@aws-crypto/supports-web-crypto": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz",
- "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- }
- },
- "node_modules/@aws-crypto/util": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz",
- "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "^3.222.0",
- "@smithy/util-utf8": "^2.0.0",
- "tslib": "^2.6.2"
- }
- },
- "node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz",
- "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz",
- "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/is-array-buffer": "^2.2.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz",
- "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/util-buffer-from": "^2.2.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-sesv2": {
- "version": "3.864.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-sesv2/-/client-sesv2-3.864.0.tgz",
- "integrity": "sha512-pwn4/3bs7ccucS9sYpMbzptEhEFQQy8TXtmKNzmyY7OIDBGTiJrxsWYDTULO4nxsMmGXi39mSEowlK4QUCyC+w==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-crypto/sha256-browser": "5.2.0",
- "@aws-crypto/sha256-js": "5.2.0",
- "@aws-sdk/core": "3.864.0",
- "@aws-sdk/credential-provider-node": "3.864.0",
- "@aws-sdk/middleware-host-header": "3.862.0",
- "@aws-sdk/middleware-logger": "3.862.0",
- "@aws-sdk/middleware-recursion-detection": "3.862.0",
- "@aws-sdk/middleware-user-agent": "3.864.0",
- "@aws-sdk/region-config-resolver": "3.862.0",
- "@aws-sdk/signature-v4-multi-region": "3.864.0",
- "@aws-sdk/types": "3.862.0",
- "@aws-sdk/util-endpoints": "3.862.0",
- "@aws-sdk/util-user-agent-browser": "3.862.0",
- "@aws-sdk/util-user-agent-node": "3.864.0",
- "@smithy/config-resolver": "^4.1.5",
- "@smithy/core": "^3.8.0",
- "@smithy/fetch-http-handler": "^5.1.1",
- "@smithy/hash-node": "^4.0.5",
- "@smithy/invalid-dependency": "^4.0.5",
- "@smithy/middleware-content-length": "^4.0.5",
- "@smithy/middleware-endpoint": "^4.1.18",
- "@smithy/middleware-retry": "^4.1.19",
- "@smithy/middleware-serde": "^4.0.9",
- "@smithy/middleware-stack": "^4.0.5",
- "@smithy/node-config-provider": "^4.1.4",
- "@smithy/node-http-handler": "^4.1.1",
- "@smithy/protocol-http": "^5.1.3",
- "@smithy/smithy-client": "^4.4.10",
- "@smithy/types": "^4.3.2",
- "@smithy/url-parser": "^4.0.5",
- "@smithy/util-base64": "^4.0.0",
- "@smithy/util-body-length-browser": "^4.0.0",
- "@smithy/util-body-length-node": "^4.0.0",
- "@smithy/util-defaults-mode-browser": "^4.0.26",
- "@smithy/util-defaults-mode-node": "^4.0.26",
- "@smithy/util-endpoints": "^3.0.7",
- "@smithy/util-middleware": "^4.0.5",
- "@smithy/util-retry": "^4.0.7",
- "@smithy/util-utf8": "^4.0.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/client-sso": {
- "version": "3.864.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.864.0.tgz",
- "integrity": "sha512-THiOp0OpQROEKZ6IdDCDNNh3qnNn/kFFaTSOiugDpgcE5QdsOxh1/RXq7LmHpTJum3cmnFf8jG59PHcz9Tjnlw==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-crypto/sha256-browser": "5.2.0",
- "@aws-crypto/sha256-js": "5.2.0",
- "@aws-sdk/core": "3.864.0",
- "@aws-sdk/middleware-host-header": "3.862.0",
- "@aws-sdk/middleware-logger": "3.862.0",
- "@aws-sdk/middleware-recursion-detection": "3.862.0",
- "@aws-sdk/middleware-user-agent": "3.864.0",
- "@aws-sdk/region-config-resolver": "3.862.0",
- "@aws-sdk/types": "3.862.0",
- "@aws-sdk/util-endpoints": "3.862.0",
- "@aws-sdk/util-user-agent-browser": "3.862.0",
- "@aws-sdk/util-user-agent-node": "3.864.0",
- "@smithy/config-resolver": "^4.1.5",
- "@smithy/core": "^3.8.0",
- "@smithy/fetch-http-handler": "^5.1.1",
- "@smithy/hash-node": "^4.0.5",
- "@smithy/invalid-dependency": "^4.0.5",
- "@smithy/middleware-content-length": "^4.0.5",
- "@smithy/middleware-endpoint": "^4.1.18",
- "@smithy/middleware-retry": "^4.1.19",
- "@smithy/middleware-serde": "^4.0.9",
- "@smithy/middleware-stack": "^4.0.5",
- "@smithy/node-config-provider": "^4.1.4",
- "@smithy/node-http-handler": "^4.1.1",
- "@smithy/protocol-http": "^5.1.3",
- "@smithy/smithy-client": "^4.4.10",
- "@smithy/types": "^4.3.2",
- "@smithy/url-parser": "^4.0.5",
- "@smithy/util-base64": "^4.0.0",
- "@smithy/util-body-length-browser": "^4.0.0",
- "@smithy/util-body-length-node": "^4.0.0",
- "@smithy/util-defaults-mode-browser": "^4.0.26",
- "@smithy/util-defaults-mode-node": "^4.0.26",
- "@smithy/util-endpoints": "^3.0.7",
- "@smithy/util-middleware": "^4.0.5",
- "@smithy/util-retry": "^4.0.7",
- "@smithy/util-utf8": "^4.0.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/core": {
- "version": "3.864.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.864.0.tgz",
- "integrity": "sha512-LFUREbobleHEln+Zf7IG83lAZwvHZG0stI7UU0CtwyuhQy5Yx0rKksHNOCmlM7MpTEbSCfntEhYi3jUaY5e5lg==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "3.862.0",
- "@aws-sdk/xml-builder": "3.862.0",
- "@smithy/core": "^3.8.0",
- "@smithy/node-config-provider": "^4.1.4",
- "@smithy/property-provider": "^4.0.5",
- "@smithy/protocol-http": "^5.1.3",
- "@smithy/signature-v4": "^5.1.3",
- "@smithy/smithy-client": "^4.4.10",
- "@smithy/types": "^4.3.2",
- "@smithy/util-base64": "^4.0.0",
- "@smithy/util-body-length-browser": "^4.0.0",
- "@smithy/util-middleware": "^4.0.5",
- "@smithy/util-utf8": "^4.0.0",
- "fast-xml-parser": "5.2.5",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-env": {
- "version": "3.864.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.864.0.tgz",
- "integrity": "sha512-StJPOI2Rt8UE6lYjXUpg6tqSZaM72xg46ljPg8kIevtBAAfdtq9K20qT/kSliWGIBocMFAv0g2mC0hAa+ECyvg==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/core": "3.864.0",
- "@aws-sdk/types": "3.862.0",
- "@smithy/property-provider": "^4.0.5",
- "@smithy/types": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-http": {
- "version": "3.864.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.864.0.tgz",
- "integrity": "sha512-E/RFVxGTuGnuD+9pFPH2j4l6HvrXzPhmpL8H8nOoJUosjx7d4v93GJMbbl1v/fkDLqW9qN4Jx2cI6PAjohA6OA==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/core": "3.864.0",
- "@aws-sdk/types": "3.862.0",
- "@smithy/fetch-http-handler": "^5.1.1",
- "@smithy/node-http-handler": "^4.1.1",
- "@smithy/property-provider": "^4.0.5",
- "@smithy/protocol-http": "^5.1.3",
- "@smithy/smithy-client": "^4.4.10",
- "@smithy/types": "^4.3.2",
- "@smithy/util-stream": "^4.2.4",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-ini": {
- "version": "3.864.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.864.0.tgz",
- "integrity": "sha512-PlxrijguR1gxyPd5EYam6OfWLarj2MJGf07DvCx9MAuQkw77HBnsu6+XbV8fQriFuoJVTBLn9ROhMr/ROAYfUg==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/core": "3.864.0",
- "@aws-sdk/credential-provider-env": "3.864.0",
- "@aws-sdk/credential-provider-http": "3.864.0",
- "@aws-sdk/credential-provider-process": "3.864.0",
- "@aws-sdk/credential-provider-sso": "3.864.0",
- "@aws-sdk/credential-provider-web-identity": "3.864.0",
- "@aws-sdk/nested-clients": "3.864.0",
- "@aws-sdk/types": "3.862.0",
- "@smithy/credential-provider-imds": "^4.0.7",
- "@smithy/property-provider": "^4.0.5",
- "@smithy/shared-ini-file-loader": "^4.0.5",
- "@smithy/types": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-node": {
- "version": "3.864.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.864.0.tgz",
- "integrity": "sha512-2BEymFeXURS+4jE9tP3vahPwbYRl0/1MVaFZcijj6pq+nf5EPGvkFillbdBRdc98ZI2NedZgSKu3gfZXgYdUhQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/credential-provider-env": "3.864.0",
- "@aws-sdk/credential-provider-http": "3.864.0",
- "@aws-sdk/credential-provider-ini": "3.864.0",
- "@aws-sdk/credential-provider-process": "3.864.0",
- "@aws-sdk/credential-provider-sso": "3.864.0",
- "@aws-sdk/credential-provider-web-identity": "3.864.0",
- "@aws-sdk/types": "3.862.0",
- "@smithy/credential-provider-imds": "^4.0.7",
- "@smithy/property-provider": "^4.0.5",
- "@smithy/shared-ini-file-loader": "^4.0.5",
- "@smithy/types": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-process": {
- "version": "3.864.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.864.0.tgz",
- "integrity": "sha512-Zxnn1hxhq7EOqXhVYgkF4rI9MnaO3+6bSg/tErnBQ3F8kDpA7CFU24G1YxwaJXp2X4aX3LwthefmSJHwcVP/2g==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/core": "3.864.0",
- "@aws-sdk/types": "3.862.0",
- "@smithy/property-provider": "^4.0.5",
- "@smithy/shared-ini-file-loader": "^4.0.5",
- "@smithy/types": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-sso": {
- "version": "3.864.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.864.0.tgz",
- "integrity": "sha512-UPyPNQbxDwHVGmgWdGg9/9yvzuedRQVF5jtMkmP565YX9pKZ8wYAcXhcYdNPWFvH0GYdB0crKOmvib+bmCuwkw==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/client-sso": "3.864.0",
- "@aws-sdk/core": "3.864.0",
- "@aws-sdk/token-providers": "3.864.0",
- "@aws-sdk/types": "3.862.0",
- "@smithy/property-provider": "^4.0.5",
- "@smithy/shared-ini-file-loader": "^4.0.5",
- "@smithy/types": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-web-identity": {
- "version": "3.864.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.864.0.tgz",
- "integrity": "sha512-nNcjPN4SYg8drLwqK0vgVeSvxeGQiD0FxOaT38mV2H8cu0C5NzpvA+14Xy+W6vT84dxgmJYKk71Cr5QL2Oz+rA==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/core": "3.864.0",
- "@aws-sdk/nested-clients": "3.864.0",
- "@aws-sdk/types": "3.862.0",
- "@smithy/property-provider": "^4.0.5",
- "@smithy/types": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-host-header": {
- "version": "3.862.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.862.0.tgz",
- "integrity": "sha512-jDje8dCFeFHfuCAxMDXBs8hy8q9NCTlyK4ThyyfAj3U4Pixly2mmzY2u7b7AyGhWsjJNx8uhTjlYq5zkQPQCYw==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "3.862.0",
- "@smithy/protocol-http": "^5.1.3",
- "@smithy/types": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-logger": {
- "version": "3.862.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.862.0.tgz",
- "integrity": "sha512-N/bXSJznNBR/i7Ofmf9+gM6dx/SPBK09ZWLKsW5iQjqKxAKn/2DozlnE54uiEs1saHZWoNDRg69Ww4XYYSlG1Q==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "3.862.0",
- "@smithy/types": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-recursion-detection": {
- "version": "3.862.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.862.0.tgz",
- "integrity": "sha512-KVoo3IOzEkTq97YKM4uxZcYFSNnMkhW/qj22csofLegZi5fk90ztUnnaeKfaEJHfHp/tm1Y3uSoOXH45s++kKQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "3.862.0",
- "@smithy/protocol-http": "^5.1.3",
- "@smithy/types": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-sdk-s3": {
- "version": "3.864.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.864.0.tgz",
- "integrity": "sha512-GjYPZ6Xnqo17NnC8NIQyvvdzzO7dm+Ks7gpxD/HsbXPmV2aEfuFveJXneGW9e1BheSKFff6FPDWu8Gaj2Iu1yg==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/core": "3.864.0",
- "@aws-sdk/types": "3.862.0",
- "@aws-sdk/util-arn-parser": "3.804.0",
- "@smithy/core": "^3.8.0",
- "@smithy/node-config-provider": "^4.1.4",
- "@smithy/protocol-http": "^5.1.3",
- "@smithy/signature-v4": "^5.1.3",
- "@smithy/smithy-client": "^4.4.10",
- "@smithy/types": "^4.3.2",
- "@smithy/util-config-provider": "^4.0.0",
- "@smithy/util-middleware": "^4.0.5",
- "@smithy/util-stream": "^4.2.4",
- "@smithy/util-utf8": "^4.0.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-user-agent": {
- "version": "3.864.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.864.0.tgz",
- "integrity": "sha512-wrddonw4EyLNSNBrApzEhpSrDwJiNfjxDm5E+bn8n32BbAojXASH8W8jNpxz/jMgNkkJNxCfyqybGKzBX0OhbQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/core": "3.864.0",
- "@aws-sdk/types": "3.862.0",
- "@aws-sdk/util-endpoints": "3.862.0",
- "@smithy/core": "^3.8.0",
- "@smithy/protocol-http": "^5.1.3",
- "@smithy/types": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/nested-clients": {
- "version": "3.864.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.864.0.tgz",
- "integrity": "sha512-H1C+NjSmz2y8Tbgh7Yy89J20yD/hVyk15hNoZDbCYkXg0M358KS7KVIEYs8E2aPOCr1sK3HBE819D/yvdMgokA==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-crypto/sha256-browser": "5.2.0",
- "@aws-crypto/sha256-js": "5.2.0",
- "@aws-sdk/core": "3.864.0",
- "@aws-sdk/middleware-host-header": "3.862.0",
- "@aws-sdk/middleware-logger": "3.862.0",
- "@aws-sdk/middleware-recursion-detection": "3.862.0",
- "@aws-sdk/middleware-user-agent": "3.864.0",
- "@aws-sdk/region-config-resolver": "3.862.0",
- "@aws-sdk/types": "3.862.0",
- "@aws-sdk/util-endpoints": "3.862.0",
- "@aws-sdk/util-user-agent-browser": "3.862.0",
- "@aws-sdk/util-user-agent-node": "3.864.0",
- "@smithy/config-resolver": "^4.1.5",
- "@smithy/core": "^3.8.0",
- "@smithy/fetch-http-handler": "^5.1.1",
- "@smithy/hash-node": "^4.0.5",
- "@smithy/invalid-dependency": "^4.0.5",
- "@smithy/middleware-content-length": "^4.0.5",
- "@smithy/middleware-endpoint": "^4.1.18",
- "@smithy/middleware-retry": "^4.1.19",
- "@smithy/middleware-serde": "^4.0.9",
- "@smithy/middleware-stack": "^4.0.5",
- "@smithy/node-config-provider": "^4.1.4",
- "@smithy/node-http-handler": "^4.1.1",
- "@smithy/protocol-http": "^5.1.3",
- "@smithy/smithy-client": "^4.4.10",
- "@smithy/types": "^4.3.2",
- "@smithy/url-parser": "^4.0.5",
- "@smithy/util-base64": "^4.0.0",
- "@smithy/util-body-length-browser": "^4.0.0",
- "@smithy/util-body-length-node": "^4.0.0",
- "@smithy/util-defaults-mode-browser": "^4.0.26",
- "@smithy/util-defaults-mode-node": "^4.0.26",
- "@smithy/util-endpoints": "^3.0.7",
- "@smithy/util-middleware": "^4.0.5",
- "@smithy/util-retry": "^4.0.7",
- "@smithy/util-utf8": "^4.0.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/region-config-resolver": {
- "version": "3.862.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.862.0.tgz",
- "integrity": "sha512-VisR+/HuVFICrBPY+q9novEiE4b3mvDofWqyvmxHcWM7HumTz9ZQSuEtnlB/92GVM3KDUrR9EmBHNRrfXYZkcQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "3.862.0",
- "@smithy/node-config-provider": "^4.1.4",
- "@smithy/types": "^4.3.2",
- "@smithy/util-config-provider": "^4.0.0",
- "@smithy/util-middleware": "^4.0.5",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/signature-v4-multi-region": {
- "version": "3.864.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.864.0.tgz",
- "integrity": "sha512-w2HIn/WIcUyv1bmyCpRUKHXB5KdFGzyxPkp/YK5g+/FuGdnFFYWGfcO8O+How4jwrZTarBYsAHW9ggoKvwr37w==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/middleware-sdk-s3": "3.864.0",
- "@aws-sdk/types": "3.862.0",
- "@smithy/protocol-http": "^5.1.3",
- "@smithy/signature-v4": "^5.1.3",
- "@smithy/types": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/token-providers": {
- "version": "3.864.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.864.0.tgz",
- "integrity": "sha512-gTc2QHOBo05SCwVA65dUtnJC6QERvFaPiuppGDSxoF7O5AQNK0UR/kMSenwLqN8b5E1oLYvQTv3C1idJLRX0cg==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/core": "3.864.0",
- "@aws-sdk/nested-clients": "3.864.0",
- "@aws-sdk/types": "3.862.0",
- "@smithy/property-provider": "^4.0.5",
- "@smithy/shared-ini-file-loader": "^4.0.5",
- "@smithy/types": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/types": {
- "version": "3.862.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.862.0.tgz",
- "integrity": "sha512-Bei+RL0cDxxV+lW2UezLbCYYNeJm6Nzee0TpW0FfyTRBhH9C1XQh4+x+IClriXvgBnRquTMMYsmJfvx8iyLKrg==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/util-arn-parser": {
- "version": "3.804.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.804.0.tgz",
- "integrity": "sha512-wmBJqn1DRXnZu3b4EkE6CWnoWMo1ZMvlfkqU5zPz67xx1GMaXlDCchFvKAXMjk4jn/L1O3tKnoFDNsoLV1kgNQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/util-endpoints": {
- "version": "3.862.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.862.0.tgz",
- "integrity": "sha512-eCZuScdE9MWWkHGM2BJxm726MCmWk/dlHjOKvkM0sN1zxBellBMw5JohNss1Z8/TUmnW2gb9XHTOiHuGjOdksA==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "3.862.0",
- "@smithy/types": "^4.3.2",
- "@smithy/url-parser": "^4.0.5",
- "@smithy/util-endpoints": "^3.0.7",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/util-locate-window": {
- "version": "3.804.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.804.0.tgz",
- "integrity": "sha512-zVoRfpmBVPodYlnMjgVjfGoEZagyRF5IPn3Uo6ZvOZp24chnW/FRstH7ESDHDDRga4z3V+ElUQHKpFDXWyBW5A==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/util-user-agent-browser": {
- "version": "3.862.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.862.0.tgz",
- "integrity": "sha512-BmPTlm0r9/10MMr5ND9E92r8KMZbq5ltYXYpVcUbAsnB1RJ8ASJuRoLne5F7mB3YMx0FJoOTuSq7LdQM3LgW3Q==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "3.862.0",
- "@smithy/types": "^4.3.2",
- "bowser": "^2.11.0",
- "tslib": "^2.6.2"
- }
- },
- "node_modules/@aws-sdk/util-user-agent-node": {
- "version": "3.864.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.864.0.tgz",
- "integrity": "sha512-d+FjUm2eJEpP+FRpVR3z6KzMdx1qwxEYDz8jzNKwxYLBBquaBaP/wfoMtMQKAcbrR7aT9FZVZF7zDgzNxUvQlQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/middleware-user-agent": "3.864.0",
- "@aws-sdk/types": "3.862.0",
- "@smithy/node-config-provider": "^4.1.4",
- "@smithy/types": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- },
- "peerDependencies": {
- "aws-crt": ">=1.0.0"
- },
- "peerDependenciesMeta": {
- "aws-crt": {
- "optional": true
- }
- }
- },
- "node_modules/@aws-sdk/xml-builder": {
- "version": "3.862.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.862.0.tgz",
- "integrity": "sha512-6Ed0kmC1NMbuFTEgNmamAUU1h5gShgxL1hBVLbEzUa3trX5aJBz1vU4bXaBTvOYUAnOHtiy1Ml4AMStd6hJnFA==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@babel/code-frame": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
- "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-validator-identifier": "^7.27.1",
- "js-tokens": "^4.0.0",
- "picocolors": "^1.1.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/compat-data": {
- "version": "7.28.0",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz",
- "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/core": {
- "version": "7.28.3",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.3.tgz",
- "integrity": "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@ampproject/remapping": "^2.2.0",
- "@babel/code-frame": "^7.27.1",
- "@babel/generator": "^7.28.3",
- "@babel/helper-compilation-targets": "^7.27.2",
- "@babel/helper-module-transforms": "^7.28.3",
- "@babel/helpers": "^7.28.3",
- "@babel/parser": "^7.28.3",
- "@babel/template": "^7.27.2",
- "@babel/traverse": "^7.28.3",
- "@babel/types": "^7.28.2",
- "convert-source-map": "^2.0.0",
- "debug": "^4.1.0",
- "gensync": "^1.0.0-beta.2",
- "json5": "^2.2.3",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/babel"
- }
- },
- "node_modules/@babel/core/node_modules/semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- }
- },
- "node_modules/@babel/generator": {
- "version": "7.28.3",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz",
- "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/parser": "^7.28.3",
- "@babel/types": "^7.28.2",
- "@jridgewell/gen-mapping": "^0.3.12",
- "@jridgewell/trace-mapping": "^0.3.28",
- "jsesc": "^3.0.2"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/generator/node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.30",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz",
- "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
- }
- },
- "node_modules/@babel/helper-compilation-targets": {
- "version": "7.27.2",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz",
- "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/compat-data": "^7.27.2",
- "@babel/helper-validator-option": "^7.27.1",
- "browserslist": "^4.24.0",
- "lru-cache": "^5.1.1",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
- "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "yallist": "^3.0.2"
- }
- },
- "node_modules/@babel/helper-compilation-targets/node_modules/semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- }
- },
- "node_modules/@babel/helper-globals": {
- "version": "7.28.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
- "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-module-imports": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz",
- "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/traverse": "^7.27.1",
- "@babel/types": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-module-transforms": {
- "version": "7.28.3",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz",
- "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-module-imports": "^7.27.1",
- "@babel/helper-validator-identifier": "^7.27.1",
- "@babel/traverse": "^7.28.3"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/helper-plugin-utils": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz",
- "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-string-parser": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
- "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-validator-identifier": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
- "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-validator-option": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
- "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helpers": {
- "version": "7.28.3",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.3.tgz",
- "integrity": "sha512-PTNtvUQihsAsDHMOP5pfobP8C6CM4JWXmP8DrEIt46c3r2bf87Ua1zoqevsMo9g+tWDwgWrFP5EIxuBx5RudAw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/template": "^7.27.2",
- "@babel/types": "^7.28.2"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/parser": {
- "version": "7.28.3",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.3.tgz",
- "integrity": "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.28.2"
- },
- "bin": {
- "parser": "bin/babel-parser.js"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@babel/plugin-syntax-async-generators": {
- "version": "7.8.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
- "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-bigint": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz",
- "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-class-properties": {
- "version": "7.12.13",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
- "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.12.13"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-class-static-block": {
- "version": "7.14.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz",
- "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-import-attributes": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz",
- "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-import-meta": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
- "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.10.4"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-json-strings": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
- "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-jsx": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz",
- "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
- "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.10.4"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
- "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-numeric-separator": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
- "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.10.4"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-object-rest-spread": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
- "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-optional-catch-binding": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
- "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-optional-chaining": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
- "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-private-property-in-object": {
- "version": "7.14.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz",
- "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-top-level-await": {
- "version": "7.14.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
- "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-typescript": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz",
- "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/template": {
- "version": "7.27.2",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz",
- "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.27.1",
- "@babel/parser": "^7.27.2",
- "@babel/types": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/traverse": {
- "version": "7.28.3",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.3.tgz",
- "integrity": "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.27.1",
- "@babel/generator": "^7.28.3",
- "@babel/helper-globals": "^7.28.0",
- "@babel/parser": "^7.28.3",
- "@babel/template": "^7.27.2",
- "@babel/types": "^7.28.2",
- "debug": "^4.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/types": {
- "version": "7.28.2",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz",
- "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-string-parser": "^7.27.1",
- "@babel/helper-validator-identifier": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@bcoe/v8-coverage": {
- "version": "0.2.3",
- "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
- "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@colors/colors": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz",
- "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==",
- "license": "MIT",
- "engines": {
- "node": ">=0.1.90"
- }
- },
- "node_modules/@cspotcode/source-map-support": {
- "version": "0.8.1",
- "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
- "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
- "devOptional": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/trace-mapping": "0.3.9"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@dabh/diagnostics": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz",
- "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==",
- "license": "MIT",
- "dependencies": {
- "colorspace": "1.1.x",
- "enabled": "2.0.x",
- "kuler": "^2.0.0"
- }
- },
- "node_modules/@emnapi/core": {
- "version": "1.4.5",
- "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.5.tgz",
- "integrity": "sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q==",
- "dev": true,
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@emnapi/wasi-threads": "1.0.4",
- "tslib": "^2.4.0"
- }
- },
- "node_modules/@emnapi/runtime": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.6.0.tgz",
- "integrity": "sha512-obtUmAHTMjll499P+D9A3axeJFlhdjOWdKUNs/U6QIGT7V5RjcUW1xToAzjvmgTSQhDbYn/NwfTRoJcQ2rNBxA==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "tslib": "^2.4.0"
- }
- },
- "node_modules/@emnapi/wasi-threads": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.4.tgz",
- "integrity": "sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g==",
- "dev": true,
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "tslib": "^2.4.0"
- }
- },
- "node_modules/@img/colour": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz",
- "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@img/sharp-darwin-arm64": {
- "version": "0.34.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.4.tgz",
- "integrity": "sha512-sitdlPzDVyvmINUdJle3TNHl+AG9QcwiAMsXmccqsCOMZNIdW2/7S26w0LyU8euiLVzFBL3dXPwVCq/ODnf2vA==",
- "cpu": [
- "arm64"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-darwin-arm64": "1.2.3"
- }
- },
- "node_modules/@img/sharp-darwin-x64": {
- "version": "0.34.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.4.tgz",
- "integrity": "sha512-rZheupWIoa3+SOdF/IcUe1ah4ZDpKBGWcsPX6MT0lYniH9micvIU7HQkYTfrx5Xi8u+YqwLtxC/3vl8TQN6rMg==",
- "cpu": [
- "x64"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-darwin-x64": "1.2.3"
- }
- },
- "node_modules/@img/sharp-libvips-darwin-arm64": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.3.tgz",
- "integrity": "sha512-QzWAKo7kpHxbuHqUC28DZ9pIKpSi2ts2OJnoIGI26+HMgq92ZZ4vk8iJd4XsxN+tYfNJxzH6W62X5eTcsBymHw==",
- "cpu": [
- "arm64"
- ],
- "license": "LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "darwin"
- ],
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-darwin-x64": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.3.tgz",
- "integrity": "sha512-Ju+g2xn1E2AKO6YBhxjj+ACcsPQRHT0bhpglxcEf+3uyPY+/gL8veniKoo96335ZaPo03bdDXMv0t+BBFAbmRA==",
- "cpu": [
- "x64"
- ],
- "license": "LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "darwin"
- ],
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-linux-arm": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.3.tgz",
- "integrity": "sha512-x1uE93lyP6wEwGvgAIV0gP6zmaL/a0tGzJs/BIDDG0zeBhMnuUPm7ptxGhUbcGs4okDJrk4nxgrmxpib9g6HpA==",
- "cpu": [
- "arm"
- ],
- "license": "LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "linux"
- ],
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-linux-arm64": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.3.tgz",
- "integrity": "sha512-I4RxkXU90cpufazhGPyVujYwfIm9Nk1QDEmiIsaPwdnm013F7RIceaCc87kAH+oUB1ezqEvC6ga4m7MSlqsJvQ==",
- "cpu": [
- "arm64"
- ],
- "license": "LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "linux"
- ],
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-linux-ppc64": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.3.tgz",
- "integrity": "sha512-Y2T7IsQvJLMCBM+pmPbM3bKT/yYJvVtLJGfCs4Sp95SjvnFIjynbjzsa7dY1fRJX45FTSfDksbTp6AGWudiyCg==",
- "cpu": [
- "ppc64"
- ],
- "license": "LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "linux"
- ],
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-linux-s390x": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.3.tgz",
- "integrity": "sha512-RgWrs/gVU7f+K7P+KeHFaBAJlNkD1nIZuVXdQv6S+fNA6syCcoboNjsV2Pou7zNlVdNQoQUpQTk8SWDHUA3y/w==",
- "cpu": [
- "s390x"
- ],
- "license": "LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "linux"
- ],
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-linux-x64": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.3.tgz",
- "integrity": "sha512-3JU7LmR85K6bBiRzSUc/Ff9JBVIFVvq6bomKE0e63UXGeRw2HPVEjoJke1Yx+iU4rL7/7kUjES4dZ/81Qjhyxg==",
- "cpu": [
- "x64"
- ],
- "license": "LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "linux"
- ],
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-linuxmusl-arm64": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.3.tgz",
- "integrity": "sha512-F9q83RZ8yaCwENw1GieztSfj5msz7GGykG/BA+MOUefvER69K/ubgFHNeSyUu64amHIYKGDs4sRCMzXVj8sEyw==",
- "cpu": [
- "arm64"
- ],
- "license": "LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "linux"
- ],
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-linuxmusl-x64": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.3.tgz",
- "integrity": "sha512-U5PUY5jbc45ANM6tSJpsgqmBF/VsL6LnxJmIf11kB7J5DctHgqm0SkuXzVWtIY90GnJxKnC/JT251TDnk1fu/g==",
- "cpu": [
- "x64"
- ],
- "license": "LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "linux"
- ],
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-linux-arm": {
- "version": "0.34.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.4.tgz",
- "integrity": "sha512-Xyam4mlqM0KkTHYVSuc6wXRmM7LGN0P12li03jAnZ3EJWZqj83+hi8Y9UxZUbxsgsK1qOEwg7O0Bc0LjqQVtxA==",
- "cpu": [
- "arm"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-linux-arm": "1.2.3"
- }
- },
- "node_modules/@img/sharp-linux-arm64": {
- "version": "0.34.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.4.tgz",
- "integrity": "sha512-YXU1F/mN/Wu786tl72CyJjP/Ngl8mGHN1hST4BGl+hiW5jhCnV2uRVTNOcaYPs73NeT/H8Upm3y9582JVuZHrQ==",
- "cpu": [
- "arm64"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-linux-arm64": "1.2.3"
- }
- },
- "node_modules/@img/sharp-linux-ppc64": {
- "version": "0.34.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.4.tgz",
- "integrity": "sha512-F4PDtF4Cy8L8hXA2p3TO6s4aDt93v+LKmpcYFLAVdkkD3hSxZzee0rh6/+94FpAynsuMpLX5h+LRsSG3rIciUQ==",
- "cpu": [
- "ppc64"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-linux-ppc64": "1.2.3"
- }
- },
- "node_modules/@img/sharp-linux-s390x": {
- "version": "0.34.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.4.tgz",
- "integrity": "sha512-qVrZKE9Bsnzy+myf7lFKvng6bQzhNUAYcVORq2P7bDlvmF6u2sCmK2KyEQEBdYk+u3T01pVsPrkj943T1aJAsw==",
- "cpu": [
- "s390x"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-linux-s390x": "1.2.3"
- }
- },
- "node_modules/@img/sharp-linux-x64": {
- "version": "0.34.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.4.tgz",
- "integrity": "sha512-ZfGtcp2xS51iG79c6Vhw9CWqQC8l2Ot8dygxoDoIQPTat/Ov3qAa8qpxSrtAEAJW+UjTXc4yxCjNfxm4h6Xm2A==",
- "cpu": [
- "x64"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-linux-x64": "1.2.3"
- }
- },
- "node_modules/@img/sharp-linuxmusl-arm64": {
- "version": "0.34.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.4.tgz",
- "integrity": "sha512-8hDVvW9eu4yHWnjaOOR8kHVrew1iIX+MUgwxSuH2XyYeNRtLUe4VNioSqbNkB7ZYQJj9rUTT4PyRscyk2PXFKA==",
- "cpu": [
- "arm64"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-linuxmusl-arm64": "1.2.3"
- }
- },
- "node_modules/@img/sharp-linuxmusl-x64": {
- "version": "0.34.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.4.tgz",
- "integrity": "sha512-lU0aA5L8QTlfKjpDCEFOZsTYGn3AEiO6db8W5aQDxj0nQkVrZWmN3ZP9sYKWJdtq3PWPhUNlqehWyXpYDcI9Sg==",
- "cpu": [
- "x64"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-linuxmusl-x64": "1.2.3"
- }
- },
- "node_modules/@img/sharp-wasm32": {
- "version": "0.34.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.4.tgz",
- "integrity": "sha512-33QL6ZO/qpRyG7woB/HUALz28WnTMI2W1jgX3Nu2bypqLIKx/QKMILLJzJjI+SIbvXdG9fUnmrxR7vbi1sTBeA==",
- "cpu": [
- "wasm32"
- ],
- "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
- "optional": true,
- "dependencies": {
- "@emnapi/runtime": "^1.5.0"
- },
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-win32-arm64": {
- "version": "0.34.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.4.tgz",
- "integrity": "sha512-2Q250do/5WXTwxW3zjsEuMSv5sUU4Tq9VThWKlU2EYLm4MB7ZeMwF+SFJutldYODXF6jzc6YEOC+VfX0SZQPqA==",
- "cpu": [
- "arm64"
- ],
- "license": "Apache-2.0 AND LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-win32-ia32": {
- "version": "0.34.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.4.tgz",
- "integrity": "sha512-3ZeLue5V82dT92CNL6rsal6I2weKw1cYu+rGKm8fOCCtJTR2gYeUfY3FqUnIJsMUPIH68oS5jmZ0NiJ508YpEw==",
- "cpu": [
- "ia32"
- ],
- "license": "Apache-2.0 AND LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-win32-x64": {
- "version": "0.34.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.4.tgz",
- "integrity": "sha512-xIyj4wpYs8J18sVN3mSQjwrw7fKUqRw+Z5rnHNCy5fYTxigBz81u5mOMPmFumwjcn8+ld1ppptMBCLic1nz6ig==",
- "cpu": [
- "x64"
- ],
- "license": "Apache-2.0 AND LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@isaacs/cliui": {
- "version": "8.0.2",
- "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
- "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
- "license": "ISC",
- "dependencies": {
- "string-width": "^5.1.2",
- "string-width-cjs": "npm:string-width@^4.2.0",
- "strip-ansi": "^7.0.1",
- "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
- "wrap-ansi": "^8.1.0",
- "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@istanbuljs/load-nyc-config": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
- "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "camelcase": "^5.3.1",
- "find-up": "^4.1.0",
- "get-package-type": "^0.1.0",
- "js-yaml": "^3.13.1",
- "resolve-from": "^5.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
- "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "sprintf-js": "~1.0.2"
- }
- },
- "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": {
- "version": "3.14.1",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
- "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "argparse": "^1.0.7",
- "esprima": "^4.0.0"
- },
- "bin": {
- "js-yaml": "bin/js-yaml.js"
- }
- },
- "node_modules/@istanbuljs/schema": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
- "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/@jest/console": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.0.5.tgz",
- "integrity": "sha512-xY6b0XiL0Nav3ReresUarwl2oIz1gTnxGbGpho9/rbUWsLH0f1OD/VT84xs8c7VmH7MChnLb0pag6PhZhAdDiA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/types": "30.0.5",
- "@types/node": "*",
- "chalk": "^4.1.2",
- "jest-message-util": "30.0.5",
- "jest-util": "30.0.5",
- "slash": "^3.0.0"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/@jest/core": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.0.5.tgz",
- "integrity": "sha512-fKD0OulvRsXF1hmaFgHhVJzczWzA1RXMMo9LTPuFXo9q/alDbME3JIyWYqovWsUBWSoBcsHaGPSLF9rz4l9Qeg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/console": "30.0.5",
- "@jest/pattern": "30.0.1",
- "@jest/reporters": "30.0.5",
- "@jest/test-result": "30.0.5",
- "@jest/transform": "30.0.5",
- "@jest/types": "30.0.5",
- "@types/node": "*",
- "ansi-escapes": "^4.3.2",
- "chalk": "^4.1.2",
- "ci-info": "^4.2.0",
- "exit-x": "^0.2.2",
- "graceful-fs": "^4.2.11",
- "jest-changed-files": "30.0.5",
- "jest-config": "30.0.5",
- "jest-haste-map": "30.0.5",
- "jest-message-util": "30.0.5",
- "jest-regex-util": "30.0.1",
- "jest-resolve": "30.0.5",
- "jest-resolve-dependencies": "30.0.5",
- "jest-runner": "30.0.5",
- "jest-runtime": "30.0.5",
- "jest-snapshot": "30.0.5",
- "jest-util": "30.0.5",
- "jest-validate": "30.0.5",
- "jest-watcher": "30.0.5",
- "micromatch": "^4.0.8",
- "pretty-format": "30.0.5",
- "slash": "^3.0.0"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- },
- "peerDependencies": {
- "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
- },
- "peerDependenciesMeta": {
- "node-notifier": {
- "optional": true
- }
- }
- },
- "node_modules/@jest/diff-sequences": {
- "version": "30.0.1",
- "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz",
- "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/@jest/environment": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.0.5.tgz",
- "integrity": "sha512-aRX7WoaWx1oaOkDQvCWImVQ8XNtdv5sEWgk4gxR6NXb7WBUnL5sRak4WRzIQRZ1VTWPvV4VI4mgGjNL9TeKMYA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/fake-timers": "30.0.5",
- "@jest/types": "30.0.5",
- "@types/node": "*",
- "jest-mock": "30.0.5"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/@jest/expect": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.0.5.tgz",
- "integrity": "sha512-6udac8KKrtTtC+AXZ2iUN/R7dp7Ydry+Fo6FPFnDG54wjVMnb6vW/XNlf7Xj8UDjAE3aAVAsR4KFyKk3TCXmTA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "expect": "30.0.5",
- "jest-snapshot": "30.0.5"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/@jest/expect-utils": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.0.5.tgz",
- "integrity": "sha512-F3lmTT7CXWYywoVUGTCmom0vXq3HTTkaZyTAzIy+bXSBizB7o5qzlC9VCtq0arOa8GqmNsbg/cE9C6HLn7Szew==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/get-type": "30.0.1"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/@jest/fake-timers": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.0.5.tgz",
- "integrity": "sha512-ZO5DHfNV+kgEAeP3gK3XlpJLL4U3Sz6ebl/n68Uwt64qFFs5bv4bfEEjyRGK5uM0C90ewooNgFuKMdkbEoMEXw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/types": "30.0.5",
- "@sinonjs/fake-timers": "^13.0.0",
- "@types/node": "*",
- "jest-message-util": "30.0.5",
- "jest-mock": "30.0.5",
- "jest-util": "30.0.5"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/@jest/get-type": {
- "version": "30.0.1",
- "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.0.1.tgz",
- "integrity": "sha512-AyYdemXCptSRFirI5EPazNxyPwAL0jXt3zceFjaj8NFiKP9pOi0bfXonf6qkf82z2t3QWPeLCWWw4stPBzctLw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/@jest/globals": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.0.5.tgz",
- "integrity": "sha512-7oEJT19WW4oe6HR7oLRvHxwlJk2gev0U9px3ufs8sX9PoD1Eza68KF0/tlN7X0dq/WVsBScXQGgCldA1V9Y/jA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/environment": "30.0.5",
- "@jest/expect": "30.0.5",
- "@jest/types": "30.0.5",
- "jest-mock": "30.0.5"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/@jest/pattern": {
- "version": "30.0.1",
- "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.1.tgz",
- "integrity": "sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "*",
- "jest-regex-util": "30.0.1"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/@jest/reporters": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.0.5.tgz",
- "integrity": "sha512-mafft7VBX4jzED1FwGC1o/9QUM2xebzavImZMeqnsklgcyxBto8mV4HzNSzUrryJ+8R9MFOM3HgYuDradWR+4g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@bcoe/v8-coverage": "^0.2.3",
- "@jest/console": "30.0.5",
- "@jest/test-result": "30.0.5",
- "@jest/transform": "30.0.5",
- "@jest/types": "30.0.5",
- "@jridgewell/trace-mapping": "^0.3.25",
- "@types/node": "*",
- "chalk": "^4.1.2",
- "collect-v8-coverage": "^1.0.2",
- "exit-x": "^0.2.2",
- "glob": "^10.3.10",
- "graceful-fs": "^4.2.11",
- "istanbul-lib-coverage": "^3.0.0",
- "istanbul-lib-instrument": "^6.0.0",
- "istanbul-lib-report": "^3.0.0",
- "istanbul-lib-source-maps": "^5.0.0",
- "istanbul-reports": "^3.1.3",
- "jest-message-util": "30.0.5",
- "jest-util": "30.0.5",
- "jest-worker": "30.0.5",
- "slash": "^3.0.0",
- "string-length": "^4.0.2",
- "v8-to-istanbul": "^9.0.1"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- },
- "peerDependencies": {
- "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
- },
- "peerDependenciesMeta": {
- "node-notifier": {
- "optional": true
- }
- }
- },
- "node_modules/@jest/reporters/node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.30",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz",
- "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
- }
- },
- "node_modules/@jest/schemas": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz",
- "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@sinclair/typebox": "^0.34.0"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/@jest/snapshot-utils": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.0.5.tgz",
- "integrity": "sha512-XcCQ5qWHLvi29UUrowgDFvV4t7ETxX91CbDczMnoqXPOIcZOxyNdSjm6kV5XMc8+HkxfRegU/MUmnTbJRzGrUQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/types": "30.0.5",
- "chalk": "^4.1.2",
- "graceful-fs": "^4.2.11",
- "natural-compare": "^1.4.0"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/@jest/source-map": {
- "version": "30.0.1",
- "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-30.0.1.tgz",
- "integrity": "sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/trace-mapping": "^0.3.25",
- "callsites": "^3.1.0",
- "graceful-fs": "^4.2.11"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/@jest/source-map/node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.30",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz",
- "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
- }
- },
- "node_modules/@jest/test-result": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.0.5.tgz",
- "integrity": "sha512-wPyztnK0gbDMQAJZ43tdMro+qblDHH1Ru/ylzUo21TBKqt88ZqnKKK2m30LKmLLoKtR2lxdpCC/P3g1vfKcawQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/console": "30.0.5",
- "@jest/types": "30.0.5",
- "@types/istanbul-lib-coverage": "^2.0.6",
- "collect-v8-coverage": "^1.0.2"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/@jest/test-sequencer": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.0.5.tgz",
- "integrity": "sha512-Aea/G1egWoIIozmDD7PBXUOxkekXl7ueGzrsGGi1SbeKgQqCYCIf+wfbflEbf2LiPxL8j2JZGLyrzZagjvW4YQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/test-result": "30.0.5",
- "graceful-fs": "^4.2.11",
- "jest-haste-map": "30.0.5",
- "slash": "^3.0.0"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/@jest/transform": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.0.5.tgz",
- "integrity": "sha512-Vk8amLQCmuZyy6GbBht1Jfo9RSdBtg7Lks+B0PecnjI8J+PCLQPGh7uI8Q/2wwpW2gLdiAfiHNsmekKlywULqg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/core": "^7.27.4",
- "@jest/types": "30.0.5",
- "@jridgewell/trace-mapping": "^0.3.25",
- "babel-plugin-istanbul": "^7.0.0",
- "chalk": "^4.1.2",
- "convert-source-map": "^2.0.0",
- "fast-json-stable-stringify": "^2.1.0",
- "graceful-fs": "^4.2.11",
- "jest-haste-map": "30.0.5",
- "jest-regex-util": "30.0.1",
- "jest-util": "30.0.5",
- "micromatch": "^4.0.8",
- "pirates": "^4.0.7",
- "slash": "^3.0.0",
- "write-file-atomic": "^5.0.1"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/@jest/transform/node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.30",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz",
- "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
- }
- },
- "node_modules/@jest/types": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.5.tgz",
- "integrity": "sha512-aREYa3aku9SSnea4aX6bhKn4bgv3AXkgijoQgbYV3yvbiGt6z+MQ85+6mIhx9DsKW2BuB/cLR/A+tcMThx+KLQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/pattern": "30.0.1",
- "@jest/schemas": "30.0.5",
- "@types/istanbul-lib-coverage": "^2.0.6",
- "@types/istanbul-reports": "^3.0.4",
- "@types/node": "*",
- "@types/yargs": "^17.0.33",
- "chalk": "^4.1.2"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/@jridgewell/gen-mapping": {
- "version": "0.3.13",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
- "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/sourcemap-codec": "^1.5.0",
- "@jridgewell/trace-mapping": "^0.3.24"
- }
- },
- "node_modules/@jridgewell/gen-mapping/node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.30",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz",
- "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
- }
- },
- "node_modules/@jridgewell/resolve-uri": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
- "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
- "devOptional": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.5.5",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
- "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
- "devOptional": true,
- "license": "MIT"
- },
- "node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.9",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
- "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
- "devOptional": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.0.3",
- "@jridgewell/sourcemap-codec": "^1.4.10"
- }
- },
- "node_modules/@jsdevtools/ono": {
- "version": "7.1.3",
- "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz",
- "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==",
- "license": "MIT"
- },
- "node_modules/@napi-rs/wasm-runtime": {
- "version": "0.2.12",
- "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz",
- "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==",
- "dev": true,
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@emnapi/core": "^1.4.3",
- "@emnapi/runtime": "^1.4.3",
- "@tybys/wasm-util": "^0.10.0"
- }
- },
- "node_modules/@noble/hashes": {
- "version": "1.8.0",
- "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
- "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^14.21.3 || >=16"
- },
- "funding": {
- "url": "https://paulmillr.com/funding/"
- }
- },
- "node_modules/@paralleldrive/cuid2": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.2.2.tgz",
- "integrity": "sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@noble/hashes": "^1.1.5"
- }
- },
- "node_modules/@pkgjs/parseargs": {
- "version": "0.11.0",
- "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
- "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/@pkgr/core": {
- "version": "0.2.9",
- "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz",
- "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/pkgr"
- }
- },
- "node_modules/@redis/bloom": {
- "version": "5.8.1",
- "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-5.8.1.tgz",
- "integrity": "sha512-hJOJr/yX6BttnyZ+nxD3Ddiu2lPig4XJjyAK1v7OSHOJNUTfn3RHBryB9wgnBMBdkg9glVh2AjItxIXmr600MA==",
- "license": "MIT",
- "engines": {
- "node": ">= 18"
- },
- "peerDependencies": {
- "@redis/client": "^5.8.1"
- }
- },
- "node_modules/@redis/client": {
- "version": "5.8.1",
- "resolved": "https://registry.npmjs.org/@redis/client/-/client-5.8.1.tgz",
- "integrity": "sha512-hD5Tvv7G0t8b3w8ao3kQ4jEPUmUUC6pqA18c8ciYF5xZGfUGBg0olQHW46v6qSt4O5bxOuB3uV7pM6H5wEjBwA==",
- "license": "MIT",
- "dependencies": {
- "cluster-key-slot": "1.1.2"
- },
- "engines": {
- "node": ">= 18"
- }
- },
- "node_modules/@redis/json": {
- "version": "5.8.1",
- "resolved": "https://registry.npmjs.org/@redis/json/-/json-5.8.1.tgz",
- "integrity": "sha512-kyvM8Vn+WjJI++nRsIoI9TbdfCs1/TgD0Hp7Z7GiG6W4IEBzkXGQakli+R5BoJzUfgh7gED2fkncYy1NLprMNg==",
- "license": "MIT",
- "engines": {
- "node": ">= 18"
- },
- "peerDependencies": {
- "@redis/client": "^5.8.1"
- }
- },
- "node_modules/@redis/search": {
- "version": "5.8.1",
- "resolved": "https://registry.npmjs.org/@redis/search/-/search-5.8.1.tgz",
- "integrity": "sha512-CzuKNTInTNQkxqehSn7QiYcM+th+fhjQn5ilTvksP1wPjpxqK0qWt92oYg3XZc3tO2WuXkqDvTujc4D7kb6r/A==",
- "license": "MIT",
- "engines": {
- "node": ">= 18"
- },
- "peerDependencies": {
- "@redis/client": "^5.8.1"
- }
- },
- "node_modules/@redis/time-series": {
- "version": "5.8.1",
- "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-5.8.1.tgz",
- "integrity": "sha512-klvdR96U9oSOyqvcectoAGhYlMOnMS3I5UWUOgdBn1buMODiwM/E4Eds7gxldKmtowe4rLJSF1CyIqyZTjy8Ow==",
- "license": "MIT",
- "engines": {
- "node": ">= 18"
- },
- "peerDependencies": {
- "@redis/client": "^5.8.1"
- }
- },
- "node_modules/@scarf/scarf": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.4.0.tgz",
- "integrity": "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==",
- "hasInstallScript": true,
- "license": "Apache-2.0"
- },
- "node_modules/@sinclair/typebox": {
- "version": "0.34.40",
- "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.40.tgz",
- "integrity": "sha512-gwBNIP8ZAYev/ORDWW0QvxdwPXwxBtLsdsJgSc7eDIRt8ubP+rxUBzPsrwnu16fgEF8Bx4lh/+mvQvJzcTM6Kw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@sinonjs/commons": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
- "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "type-detect": "4.0.8"
- }
- },
- "node_modules/@sinonjs/fake-timers": {
- "version": "13.0.5",
- "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz",
- "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "@sinonjs/commons": "^3.0.1"
- }
- },
- "node_modules/@smithy/abort-controller": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.5.tgz",
- "integrity": "sha512-jcrqdTQurIrBbUm4W2YdLVMQDoL0sA9DTxYd2s+R/y+2U9NLOP7Xf/YqfSg1FZhlZIYEnvk2mwbyvIfdLEPo8g==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/config-resolver": {
- "version": "4.1.5",
- "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.1.5.tgz",
- "integrity": "sha512-viuHMxBAqydkB0AfWwHIdwf/PRH2z5KHGUzqyRtS/Wv+n3IHI993Sk76VCA7dD/+GzgGOmlJDITfPcJC1nIVIw==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/node-config-provider": "^4.1.4",
- "@smithy/types": "^4.3.2",
- "@smithy/util-config-provider": "^4.0.0",
- "@smithy/util-middleware": "^4.0.5",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/core": {
- "version": "3.8.0",
- "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.8.0.tgz",
- "integrity": "sha512-EYqsIYJmkR1VhVE9pccnk353xhs+lB6btdutJEtsp7R055haMJp2yE16eSxw8fv+G0WUY6vqxyYOP8kOqawxYQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/middleware-serde": "^4.0.9",
- "@smithy/protocol-http": "^5.1.3",
- "@smithy/types": "^4.3.2",
- "@smithy/util-base64": "^4.0.0",
- "@smithy/util-body-length-browser": "^4.0.0",
- "@smithy/util-middleware": "^4.0.5",
- "@smithy/util-stream": "^4.2.4",
- "@smithy/util-utf8": "^4.0.0",
- "@types/uuid": "^9.0.1",
- "tslib": "^2.6.2",
- "uuid": "^9.0.1"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/core/node_modules/@types/uuid": {
- "version": "9.0.8",
- "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz",
- "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@smithy/core/node_modules/uuid": {
- "version": "9.0.1",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
- "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
- "dev": true,
- "funding": [
- "https://github.com/sponsors/broofa",
- "https://github.com/sponsors/ctavan"
- ],
- "license": "MIT",
- "bin": {
- "uuid": "dist/bin/uuid"
- }
- },
- "node_modules/@smithy/credential-provider-imds": {
- "version": "4.0.7",
- "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.0.7.tgz",
- "integrity": "sha512-dDzrMXA8d8riFNiPvytxn0mNwR4B3h8lgrQ5UjAGu6T9z/kRg/Xncf4tEQHE/+t25sY8IH3CowcmWi+1U5B1Gw==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/node-config-provider": "^4.1.4",
- "@smithy/property-provider": "^4.0.5",
- "@smithy/types": "^4.3.2",
- "@smithy/url-parser": "^4.0.5",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/fetch-http-handler": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.1.1.tgz",
- "integrity": "sha512-61WjM0PWmZJR+SnmzaKI7t7G0UkkNFboDpzIdzSoy7TByUzlxo18Qlh9s71qug4AY4hlH/CwXdubMtkcNEb/sQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/protocol-http": "^5.1.3",
- "@smithy/querystring-builder": "^4.0.5",
- "@smithy/types": "^4.3.2",
- "@smithy/util-base64": "^4.0.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/hash-node": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.0.5.tgz",
- "integrity": "sha512-cv1HHkKhpyRb6ahD8Vcfb2Hgz67vNIXEp2vnhzfxLFGRukLCNEA5QdsorbUEzXma1Rco0u3rx5VTqbM06GcZqQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.3.2",
- "@smithy/util-buffer-from": "^4.0.0",
- "@smithy/util-utf8": "^4.0.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/invalid-dependency": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.0.5.tgz",
- "integrity": "sha512-IVnb78Qtf7EJpoEVo7qJ8BEXQwgC4n3igeJNNKEj/MLYtapnx8A67Zt/J3RXAj2xSO1910zk0LdFiygSemuLow==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/is-array-buffer": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.0.0.tgz",
- "integrity": "sha512-saYhF8ZZNoJDTvJBEWgeBccCg+yvp1CX+ed12yORU3NilJScfc6gfch2oVb4QgxZrGUx3/ZJlb+c/dJbyupxlw==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/middleware-content-length": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.0.5.tgz",
- "integrity": "sha512-l1jlNZoYzoCC7p0zCtBDE5OBXZ95yMKlRlftooE5jPWQn4YBPLgsp+oeHp7iMHaTGoUdFqmHOPa8c9G3gBsRpQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/protocol-http": "^5.1.3",
- "@smithy/types": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/middleware-endpoint": {
- "version": "4.1.18",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.1.18.tgz",
- "integrity": "sha512-ZhvqcVRPZxnZlokcPaTwb+r+h4yOIOCJmx0v2d1bpVlmP465g3qpVSf7wxcq5zZdu4jb0H4yIMxuPwDJSQc3MQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/core": "^3.8.0",
- "@smithy/middleware-serde": "^4.0.9",
- "@smithy/node-config-provider": "^4.1.4",
- "@smithy/shared-ini-file-loader": "^4.0.5",
- "@smithy/types": "^4.3.2",
- "@smithy/url-parser": "^4.0.5",
- "@smithy/util-middleware": "^4.0.5",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/middleware-retry": {
- "version": "4.1.19",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.1.19.tgz",
- "integrity": "sha512-X58zx/NVECjeuUB6A8HBu4bhx72EoUz+T5jTMIyeNKx2lf+Gs9TmWPNNkH+5QF0COjpInP/xSpJGJ7xEnAklQQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/node-config-provider": "^4.1.4",
- "@smithy/protocol-http": "^5.1.3",
- "@smithy/service-error-classification": "^4.0.7",
- "@smithy/smithy-client": "^4.4.10",
- "@smithy/types": "^4.3.2",
- "@smithy/util-middleware": "^4.0.5",
- "@smithy/util-retry": "^4.0.7",
- "@types/uuid": "^9.0.1",
- "tslib": "^2.6.2",
- "uuid": "^9.0.1"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/middleware-retry/node_modules/@types/uuid": {
- "version": "9.0.8",
- "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz",
- "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@smithy/middleware-retry/node_modules/uuid": {
- "version": "9.0.1",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
- "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
- "dev": true,
- "funding": [
- "https://github.com/sponsors/broofa",
- "https://github.com/sponsors/ctavan"
- ],
- "license": "MIT",
- "bin": {
- "uuid": "dist/bin/uuid"
- }
- },
- "node_modules/@smithy/middleware-serde": {
- "version": "4.0.9",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.0.9.tgz",
- "integrity": "sha512-uAFFR4dpeoJPGz8x9mhxp+RPjo5wW0QEEIPPPbLXiRRWeCATf/Km3gKIVR5vaP8bN1kgsPhcEeh+IZvUlBv6Xg==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/protocol-http": "^5.1.3",
- "@smithy/types": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/middleware-stack": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.0.5.tgz",
- "integrity": "sha512-/yoHDXZPh3ocRVyeWQFvC44u8seu3eYzZRveCMfgMOBcNKnAmOvjbL9+Cp5XKSIi9iYA9PECUuW2teDAk8T+OQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/node-config-provider": {
- "version": "4.1.4",
- "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.1.4.tgz",
- "integrity": "sha512-+UDQV/k42jLEPPHSn39l0Bmc4sB1xtdI9Gd47fzo/0PbXzJ7ylgaOByVjF5EeQIumkepnrJyfx86dPa9p47Y+w==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/property-provider": "^4.0.5",
- "@smithy/shared-ini-file-loader": "^4.0.5",
- "@smithy/types": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/node-http-handler": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.1.1.tgz",
- "integrity": "sha512-RHnlHqFpoVdjSPPiYy/t40Zovf3BBHc2oemgD7VsVTFFZrU5erFFe0n52OANZZ/5sbshgD93sOh5r6I35Xmpaw==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/abort-controller": "^4.0.5",
- "@smithy/protocol-http": "^5.1.3",
- "@smithy/querystring-builder": "^4.0.5",
- "@smithy/types": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/property-provider": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.0.5.tgz",
- "integrity": "sha512-R/bswf59T/n9ZgfgUICAZoWYKBHcsVDurAGX88zsiUtOTA/xUAPyiT+qkNCPwFn43pZqN84M4MiUsbSGQmgFIQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/protocol-http": {
- "version": "5.1.3",
- "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.1.3.tgz",
- "integrity": "sha512-fCJd2ZR7D22XhDY0l+92pUag/7je2BztPRQ01gU5bMChcyI0rlly7QFibnYHzcxDvccMjlpM/Q1ev8ceRIb48w==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/querystring-builder": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.5.tgz",
- "integrity": "sha512-NJeSCU57piZ56c+/wY+AbAw6rxCCAOZLCIniRE7wqvndqxcKKDOXzwWjrY7wGKEISfhL9gBbAaWWgHsUGedk+A==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.3.2",
- "@smithy/util-uri-escape": "^4.0.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/querystring-parser": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.0.5.tgz",
- "integrity": "sha512-6SV7md2CzNG/WUeTjVe6Dj8noH32r4MnUeFKZrnVYsQxpGSIcphAanQMayi8jJLZAWm6pdM9ZXvKCpWOsIGg0w==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/service-error-classification": {
- "version": "4.0.7",
- "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.0.7.tgz",
- "integrity": "sha512-XvRHOipqpwNhEjDf2L5gJowZEm5nsxC16pAZOeEcsygdjv9A2jdOh3YoDQvOXBGTsaJk6mNWtzWalOB9976Wlg==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.3.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/shared-ini-file-loader": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.0.5.tgz",
- "integrity": "sha512-YVVwehRDuehgoXdEL4r1tAAzdaDgaC9EQvhK0lEbfnbrd0bd5+CTQumbdPryX3J2shT7ZqQE+jPW4lmNBAB8JQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/signature-v4": {
- "version": "5.1.3",
- "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.1.3.tgz",
- "integrity": "sha512-mARDSXSEgllNzMw6N+mC+r1AQlEBO3meEAkR/UlfAgnMzJUB3goRBWgip1EAMG99wh36MDqzo86SfIX5Y+VEaw==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/is-array-buffer": "^4.0.0",
- "@smithy/protocol-http": "^5.1.3",
- "@smithy/types": "^4.3.2",
- "@smithy/util-hex-encoding": "^4.0.0",
- "@smithy/util-middleware": "^4.0.5",
- "@smithy/util-uri-escape": "^4.0.0",
- "@smithy/util-utf8": "^4.0.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/smithy-client": {
- "version": "4.4.10",
- "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.4.10.tgz",
- "integrity": "sha512-iW6HjXqN0oPtRS0NK/zzZ4zZeGESIFcxj2FkWed3mcK8jdSdHzvnCKXSjvewESKAgGKAbJRA+OsaqKhkdYRbQQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/core": "^3.8.0",
- "@smithy/middleware-endpoint": "^4.1.18",
- "@smithy/middleware-stack": "^4.0.5",
- "@smithy/protocol-http": "^5.1.3",
- "@smithy/types": "^4.3.2",
- "@smithy/util-stream": "^4.2.4",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/types": {
- "version": "4.3.2",
- "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.3.2.tgz",
- "integrity": "sha512-QO4zghLxiQ5W9UZmX2Lo0nta2PuE1sSrXUYDoaB6HMR762C0P7v/HEPHf6ZdglTVssJG1bsrSBxdc3quvDSihw==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/url-parser": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.0.5.tgz",
- "integrity": "sha512-j+733Um7f1/DXjYhCbvNXABV53NyCRRA54C7bNEIxNPs0YjfRxeMKjjgm2jvTYrciZyCjsicHwQ6Q0ylo+NAUw==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/querystring-parser": "^4.0.5",
- "@smithy/types": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-base64": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.0.0.tgz",
- "integrity": "sha512-CvHfCmO2mchox9kjrtzoHkWHxjHZzaFojLc8quxXY7WAAMAg43nuxwv95tATVgQFNDwd4M9S1qFzj40Ul41Kmg==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/util-buffer-from": "^4.0.0",
- "@smithy/util-utf8": "^4.0.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-body-length-browser": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.0.0.tgz",
- "integrity": "sha512-sNi3DL0/k64/LO3A256M+m3CDdG6V7WKWHdAiBBMUN8S3hK3aMPhwnPik2A/a2ONN+9doY9UxaLfgqsIRg69QA==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-body-length-node": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.0.0.tgz",
- "integrity": "sha512-q0iDP3VsZzqJyje8xJWEJCNIu3lktUGVoSy1KB0UWym2CL1siV3artm+u1DFYTLejpsrdGyCSWBdGNjJzfDPjg==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-buffer-from": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.0.0.tgz",
- "integrity": "sha512-9TOQ7781sZvddgO8nxueKi3+yGvkY35kotA0Y6BWRajAv8jjmigQ1sBwz0UX47pQMYXJPahSKEKYFgt+rXdcug==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/is-array-buffer": "^4.0.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-config-provider": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.0.0.tgz",
- "integrity": "sha512-L1RBVzLyfE8OXH+1hsJ8p+acNUSirQnWQ6/EgpchV88G6zGBTDPdXiiExei6Z1wR2RxYvxY/XLw6AMNCCt8H3w==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-defaults-mode-browser": {
- "version": "4.0.26",
- "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.26.tgz",
- "integrity": "sha512-xgl75aHIS/3rrGp7iTxQAOELYeyiwBu+eEgAk4xfKwJJ0L8VUjhO2shsDpeil54BOFsqmk5xfdesiewbUY5tKQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/property-provider": "^4.0.5",
- "@smithy/smithy-client": "^4.4.10",
- "@smithy/types": "^4.3.2",
- "bowser": "^2.11.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-defaults-mode-node": {
- "version": "4.0.26",
- "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.26.tgz",
- "integrity": "sha512-z81yyIkGiLLYVDetKTUeCZQ8x20EEzvQjrqJtb/mXnevLq2+w3XCEWTJ2pMp401b6BkEkHVfXb/cROBpVauLMQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/config-resolver": "^4.1.5",
- "@smithy/credential-provider-imds": "^4.0.7",
- "@smithy/node-config-provider": "^4.1.4",
- "@smithy/property-provider": "^4.0.5",
- "@smithy/smithy-client": "^4.4.10",
- "@smithy/types": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-endpoints": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.0.7.tgz",
- "integrity": "sha512-klGBP+RpBp6V5JbrY2C/VKnHXn3d5V2YrifZbmMY8os7M6m8wdYFoO6w/fe5VkP+YVwrEktW3IWYaSQVNZJ8oQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/node-config-provider": "^4.1.4",
- "@smithy/types": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-hex-encoding": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.0.0.tgz",
- "integrity": "sha512-Yk5mLhHtfIgW2W2WQZWSg5kuMZCVbvhFmC7rV4IO2QqnZdbEFPmQnCcGMAX2z/8Qj3B9hYYNjZOhWym+RwhePw==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-middleware": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.0.5.tgz",
- "integrity": "sha512-N40PfqsZHRSsByGB81HhSo+uvMxEHT+9e255S53pfBw/wI6WKDI7Jw9oyu5tJTLwZzV5DsMha3ji8jk9dsHmQQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-retry": {
- "version": "4.0.7",
- "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.0.7.tgz",
- "integrity": "sha512-TTO6rt0ppK70alZpkjwy+3nQlTiqNfoXja+qwuAchIEAIoSZW8Qyd76dvBv3I5bCpE38APafG23Y/u270NspiQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/service-error-classification": "^4.0.7",
- "@smithy/types": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-stream": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.2.4.tgz",
- "integrity": "sha512-vSKnvNZX2BXzl0U2RgCLOwWaAP9x/ddd/XobPK02pCbzRm5s55M53uwb1rl/Ts7RXZvdJZerPkA+en2FDghLuQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/fetch-http-handler": "^5.1.1",
- "@smithy/node-http-handler": "^4.1.1",
- "@smithy/types": "^4.3.2",
- "@smithy/util-base64": "^4.0.0",
- "@smithy/util-buffer-from": "^4.0.0",
- "@smithy/util-hex-encoding": "^4.0.0",
- "@smithy/util-utf8": "^4.0.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-uri-escape": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.0.0.tgz",
- "integrity": "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-utf8": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.0.0.tgz",
- "integrity": "sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/util-buffer-from": "^4.0.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@socket.io/component-emitter": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz",
- "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==",
- "license": "MIT"
- },
- "node_modules/@sqltools/formatter": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz",
- "integrity": "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==",
- "license": "MIT"
- },
- "node_modules/@tsconfig/node10": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz",
- "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==",
- "devOptional": true,
- "license": "MIT"
- },
- "node_modules/@tsconfig/node12": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
- "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
- "devOptional": true,
- "license": "MIT"
- },
- "node_modules/@tsconfig/node14": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
- "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
- "devOptional": true,
- "license": "MIT"
- },
- "node_modules/@tsconfig/node16": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
- "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
- "devOptional": true,
- "license": "MIT"
- },
- "node_modules/@tybys/wasm-util": {
- "version": "0.10.0",
- "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.0.tgz",
- "integrity": "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==",
- "dev": true,
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "tslib": "^2.4.0"
- }
- },
- "node_modules/@types/babel__core": {
- "version": "7.20.5",
- "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
- "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/parser": "^7.20.7",
- "@babel/types": "^7.20.7",
- "@types/babel__generator": "*",
- "@types/babel__template": "*",
- "@types/babel__traverse": "*"
- }
- },
- "node_modules/@types/babel__generator": {
- "version": "7.27.0",
- "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
- "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.0.0"
- }
- },
- "node_modules/@types/babel__template": {
- "version": "7.4.4",
- "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
- "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/parser": "^7.1.0",
- "@babel/types": "^7.0.0"
- }
- },
- "node_modules/@types/babel__traverse": {
- "version": "7.28.0",
- "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
- "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.28.2"
- }
- },
- "node_modules/@types/bcrypt": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-6.0.0.tgz",
- "integrity": "sha512-/oJGukuH3D2+D+3H4JWLaAsJ/ji86dhRidzZ/Od7H/i8g+aCmvkeCc6Ni/f9uxGLSQVCRZkX2/lqEFG2BvWtlQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/body-parser": {
- "version": "1.19.6",
- "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz",
- "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/connect": "*",
- "@types/node": "*"
- }
- },
- "node_modules/@types/connect": {
- "version": "3.4.38",
- "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
- "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/cookie-parser": {
- "version": "1.4.9",
- "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.9.tgz",
- "integrity": "sha512-tGZiZ2Gtc4m3wIdLkZ8mkj1T6CEHb35+VApbL2T14Dew8HA7c+04dmKqsKRNC+8RJPm16JEK0tFSwdZqubfc4g==",
- "dev": true,
- "license": "MIT",
- "peerDependencies": {
- "@types/express": "*"
- }
- },
- "node_modules/@types/cookiejar": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz",
- "integrity": "sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/cors": {
- "version": "2.8.19",
- "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz",
- "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==",
- "license": "MIT",
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/express": {
- "version": "5.0.3",
- "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.3.tgz",
- "integrity": "sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/body-parser": "*",
- "@types/express-serve-static-core": "^5.0.0",
- "@types/serve-static": "*"
- }
- },
- "node_modules/@types/express-serve-static-core": {
- "version": "5.0.7",
- "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.7.tgz",
- "integrity": "sha512-R+33OsgWw7rOhD1emjU7dzCDHucJrgJXMA5PYCzJxVil0dsyx5iBEPHqpPfiKNJQb7lZ1vxwoLR4Z87bBUpeGQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "*",
- "@types/qs": "*",
- "@types/range-parser": "*",
- "@types/send": "*"
- }
- },
- "node_modules/@types/http-errors": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz",
- "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/istanbul-lib-coverage": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
- "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/istanbul-lib-report": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz",
- "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/istanbul-lib-coverage": "*"
- }
- },
- "node_modules/@types/istanbul-reports": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz",
- "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/istanbul-lib-report": "*"
- }
- },
- "node_modules/@types/jest": {
- "version": "30.0.0",
- "resolved": "https://registry.npmjs.org/@types/jest/-/jest-30.0.0.tgz",
- "integrity": "sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "expect": "^30.0.0",
- "pretty-format": "^30.0.0"
- }
- },
- "node_modules/@types/json-schema": {
- "version": "7.0.15",
- "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
- "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
- "license": "MIT"
- },
- "node_modules/@types/jsonwebtoken": {
- "version": "9.0.10",
- "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz",
- "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/ms": "*",
- "@types/node": "*"
- }
- },
- "node_modules/@types/methods": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/@types/methods/-/methods-1.1.4.tgz",
- "integrity": "sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/mime": {
- "version": "1.3.5",
- "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
- "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/ms": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz",
- "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/multer": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/@types/multer/-/multer-2.0.0.tgz",
- "integrity": "sha512-C3Z9v9Evij2yST3RSBktxP9STm6OdMc5uR1xF1SGr98uv8dUlAL2hqwrZ3GVB3uyMyiegnscEK6PGtYvNrjTjw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/express": "*"
- }
- },
- "node_modules/@types/node": {
- "version": "24.3.3",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.3.tgz",
- "integrity": "sha512-GKBNHjoNw3Kra1Qg5UXttsY5kiWMEfoHq2TmXb+b1rcm6N7B3wTrFYIf/oSZ1xNQ+hVVijgLkiDZh7jRRsh+Gw==",
- "license": "MIT",
- "dependencies": {
- "undici-types": "~7.10.0"
- }
- },
- "node_modules/@types/nodemailer": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-7.0.1.tgz",
- "integrity": "sha512-UfHAghPmGZVzaL8x9y+mKZMWyHC399+iq0MOmya5tIyenWX3lcdSb60vOmp0DocR6gCDTYTozv/ULQnREyyjkg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@aws-sdk/client-sesv2": "^3.839.0",
- "@types/node": "*"
- }
- },
- "node_modules/@types/pg": {
- "version": "8.15.5",
- "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.15.5.tgz",
- "integrity": "sha512-LF7lF6zWEKxuT3/OR8wAZGzkg4ENGXFNyiV/JeOt9z5B+0ZVwbql9McqX5c/WStFq1GaGso7H1AzP/qSzmlCKQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "*",
- "pg-protocol": "*",
- "pg-types": "^2.2.0"
- }
- },
- "node_modules/@types/qs": {
- "version": "6.14.0",
- "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz",
- "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/range-parser": {
- "version": "1.2.7",
- "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
- "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/redis": {
- "version": "4.0.10",
- "resolved": "https://registry.npmjs.org/@types/redis/-/redis-4.0.10.tgz",
- "integrity": "sha512-7CLy5b5fzzEGVcOccgZjoMlNpPhX6d10jEeRy2YWbFuaMNrSPc9ExRsMYsd+0VxvEHucf4EWx24Ja7cSU1FGUA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "redis": "*"
- }
- },
- "node_modules/@types/send": {
- "version": "0.17.5",
- "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz",
- "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/mime": "^1",
- "@types/node": "*"
- }
- },
- "node_modules/@types/serve-static": {
- "version": "1.15.8",
- "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.8.tgz",
- "integrity": "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/http-errors": "*",
- "@types/node": "*",
- "@types/send": "*"
- }
- },
- "node_modules/@types/socket.io": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/@types/socket.io/-/socket.io-3.0.1.tgz",
- "integrity": "sha512-XSma2FhVD78ymvoxYV4xGXrIH/0EKQ93rR+YR0Y+Kw1xbPzLDCip/UWSejZ08FpxYeYNci/PZPQS9anrvJRqMA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "socket.io": "*"
- }
- },
- "node_modules/@types/socket.io-client": {
- "version": "1.4.36",
- "resolved": "https://registry.npmjs.org/@types/socket.io-client/-/socket.io-client-1.4.36.tgz",
- "integrity": "sha512-ZJWjtFBeBy1kRSYpVbeGYTElf6BqPQUkXDlHHD4k/42byCN5Rh027f4yARHCink9sKAkbtGZXEAmR0ZCnc2/Ag==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/stack-utils": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
- "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/superagent": {
- "version": "8.1.9",
- "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.9.tgz",
- "integrity": "sha512-pTVjI73witn+9ILmoJdajHGW2jkSaOzhiFYF1Rd3EQ94kymLqB9PjD9ISg7WaALC7+dCHT0FGe9T2LktLq/3GQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/cookiejar": "^2.1.5",
- "@types/methods": "^1.1.4",
- "@types/node": "*",
- "form-data": "^4.0.0"
- }
- },
- "node_modules/@types/supertest": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-6.0.3.tgz",
- "integrity": "sha512-8WzXq62EXFhJ7QsH3Ocb/iKQ/Ty9ZVWnVzoTKc9tyyFRRF3a74Tk2+TLFgaFFw364Ere+npzHKEJ6ga2LzIL7w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/methods": "^1.1.4",
- "@types/superagent": "^8.1.0"
- }
- },
- "node_modules/@types/swagger-jsdoc": {
- "version": "6.0.4",
- "resolved": "https://registry.npmjs.org/@types/swagger-jsdoc/-/swagger-jsdoc-6.0.4.tgz",
- "integrity": "sha512-W+Xw5epcOZrF/AooUM/PccNMSAFOKWZA5dasNyMujTwsBkU74njSJBpvCCJhHAJ95XRMzQrrW844Btu0uoetwQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/swagger-ui-express": {
- "version": "4.1.8",
- "resolved": "https://registry.npmjs.org/@types/swagger-ui-express/-/swagger-ui-express-4.1.8.tgz",
- "integrity": "sha512-AhZV8/EIreHFmBV5wAs0gzJUNq9JbbSXgJLQubCC0jtIo6prnI9MIRRxnU4MZX9RB9yXxF1V4R7jtLl/Wcj31g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/express": "*",
- "@types/serve-static": "*"
- }
- },
- "node_modules/@types/triple-beam": {
- "version": "1.3.5",
- "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz",
- "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==",
- "license": "MIT"
- },
- "node_modules/@types/uuid": {
- "version": "10.0.0",
- "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz",
- "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/yargs": {
- "version": "17.0.33",
- "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
- "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/yargs-parser": "*"
- }
- },
- "node_modules/@types/yargs-parser": {
- "version": "21.0.3",
- "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz",
- "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@ungap/structured-clone": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz",
- "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/@unrs/resolver-binding-android-arm-eabi": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz",
- "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ]
- },
- "node_modules/@unrs/resolver-binding-android-arm64": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz",
- "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ]
- },
- "node_modules/@unrs/resolver-binding-darwin-arm64": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz",
- "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ]
- },
- "node_modules/@unrs/resolver-binding-darwin-x64": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz",
- "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ]
- },
- "node_modules/@unrs/resolver-binding-freebsd-x64": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz",
- "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ]
- },
- "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz",
- "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz",
- "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@unrs/resolver-binding-linux-arm64-gnu": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz",
- "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@unrs/resolver-binding-linux-arm64-musl": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz",
- "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz",
- "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz",
- "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@unrs/resolver-binding-linux-riscv64-musl": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz",
- "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@unrs/resolver-binding-linux-s390x-gnu": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz",
- "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==",
- "cpu": [
- "s390x"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@unrs/resolver-binding-linux-x64-gnu": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz",
- "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@unrs/resolver-binding-linux-x64-musl": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz",
- "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@unrs/resolver-binding-wasm32-wasi": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz",
- "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==",
- "cpu": [
- "wasm32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@napi-rs/wasm-runtime": "^0.2.11"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@unrs/resolver-binding-win32-arm64-msvc": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz",
- "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@unrs/resolver-binding-win32-ia32-msvc": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz",
- "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@unrs/resolver-binding-win32-x64-msvc": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz",
- "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@zxing/text-encoding": {
- "version": "0.9.0",
- "resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz",
- "integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==",
- "license": "(Unlicense OR Apache-2.0)",
- "optional": true
- },
- "node_modules/accepts": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
- "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==",
- "license": "MIT",
- "dependencies": {
- "mime-types": "^3.0.0",
- "negotiator": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/acorn": {
- "version": "8.15.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
- "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
- "devOptional": true,
- "license": "MIT",
- "bin": {
- "acorn": "bin/acorn"
- },
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/acorn-walk": {
- "version": "8.3.4",
- "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
- "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
- "devOptional": true,
- "license": "MIT",
- "dependencies": {
- "acorn": "^8.11.0"
- },
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/ansi-escapes": {
- "version": "4.3.2",
- "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
- "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "type-fest": "^0.21.3"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/ansi-regex": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz",
- "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-regex?sponsor=1"
- }
- },
- "node_modules/ansi-styles": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
- "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/ansis": {
- "version": "3.17.0",
- "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.17.0.tgz",
- "integrity": "sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg==",
- "license": "ISC",
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/anymatch": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
- "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "normalize-path": "^3.0.0",
- "picomatch": "^2.0.4"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/app-root-path": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.1.0.tgz",
- "integrity": "sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==",
- "license": "MIT",
- "engines": {
- "node": ">= 6.0.0"
- }
- },
- "node_modules/append-field": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
- "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==",
- "license": "MIT"
- },
- "node_modules/arg": {
- "version": "4.1.3",
- "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
- "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
- "devOptional": true,
- "license": "MIT"
- },
- "node_modules/argparse": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
- "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "license": "Python-2.0"
- },
- "node_modules/asap": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
- "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/async": {
- "version": "3.2.6",
- "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
- "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==",
- "license": "MIT"
- },
- "node_modules/asynckit": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
- "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/available-typed-arrays": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
- "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
- "license": "MIT",
- "dependencies": {
- "possible-typed-array-names": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/babel-jest": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.0.5.tgz",
- "integrity": "sha512-mRijnKimhGDMsizTvBTWotwNpzrkHr+VvZUQBof2AufXKB8NXrL1W69TG20EvOz7aevx6FTJIaBuBkYxS8zolg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/transform": "30.0.5",
- "@types/babel__core": "^7.20.5",
- "babel-plugin-istanbul": "^7.0.0",
- "babel-preset-jest": "30.0.1",
- "chalk": "^4.1.2",
- "graceful-fs": "^4.2.11",
- "slash": "^3.0.0"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.11.0"
- }
- },
- "node_modules/babel-plugin-istanbul": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.0.tgz",
- "integrity": "sha512-C5OzENSx/A+gt7t4VH1I2XsflxyPUmXRFPKBxt33xncdOmq7oROVM3bZv9Ysjjkv8OJYDMa+tKuKMvqU/H3xdw==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.0.0",
- "@istanbuljs/load-nyc-config": "^1.0.0",
- "@istanbuljs/schema": "^0.1.3",
- "istanbul-lib-instrument": "^6.0.2",
- "test-exclude": "^6.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/babel-plugin-jest-hoist": {
- "version": "30.0.1",
- "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.0.1.tgz",
- "integrity": "sha512-zTPME3pI50NsFW8ZBaVIOeAxzEY7XHlmWeXXu9srI+9kNfzCUTy8MFan46xOGZY8NZThMqq+e3qZUKsvXbasnQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/template": "^7.27.2",
- "@babel/types": "^7.27.3",
- "@types/babel__core": "^7.20.5"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/babel-preset-current-node-syntax": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz",
- "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/plugin-syntax-async-generators": "^7.8.4",
- "@babel/plugin-syntax-bigint": "^7.8.3",
- "@babel/plugin-syntax-class-properties": "^7.12.13",
- "@babel/plugin-syntax-class-static-block": "^7.14.5",
- "@babel/plugin-syntax-import-attributes": "^7.24.7",
- "@babel/plugin-syntax-import-meta": "^7.10.4",
- "@babel/plugin-syntax-json-strings": "^7.8.3",
- "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
- "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
- "@babel/plugin-syntax-numeric-separator": "^7.10.4",
- "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
- "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
- "@babel/plugin-syntax-optional-chaining": "^7.8.3",
- "@babel/plugin-syntax-private-property-in-object": "^7.14.5",
- "@babel/plugin-syntax-top-level-await": "^7.14.5"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0 || ^8.0.0-0"
- }
- },
- "node_modules/babel-preset-jest": {
- "version": "30.0.1",
- "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.0.1.tgz",
- "integrity": "sha512-+YHejD5iTWI46cZmcc/YtX4gaKBtdqCHCVfuVinizVpbmyjO3zYmeuyFdfA8duRqQZfgCAMlsfmkVbJ+e2MAJw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "babel-plugin-jest-hoist": "30.0.1",
- "babel-preset-current-node-syntax": "^1.1.0"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.11.0"
- }
- },
- "node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "license": "MIT"
- },
- "node_modules/base64-js": {
- "version": "1.5.1",
- "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/base64id": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
- "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==",
- "license": "MIT",
- "engines": {
- "node": "^4.5.0 || >= 5.9"
- }
- },
- "node_modules/bcrypt": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz",
- "integrity": "sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg==",
- "hasInstallScript": true,
- "license": "MIT",
- "dependencies": {
- "node-addon-api": "^8.3.0",
- "node-gyp-build": "^4.8.4"
- },
- "engines": {
- "node": ">= 18"
- }
- },
- "node_modules/binary-extensions": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
- "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/block-stream2": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/block-stream2/-/block-stream2-2.1.0.tgz",
- "integrity": "sha512-suhjmLI57Ewpmq00qaygS8UgEq2ly2PCItenIyhMqVjo4t4pGzqMvfgJuX8iWTeSDdfSSqS6j38fL4ToNL7Pfg==",
- "license": "MIT",
- "dependencies": {
- "readable-stream": "^3.4.0"
- }
- },
- "node_modules/body-parser": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz",
- "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==",
- "license": "MIT",
- "dependencies": {
- "bytes": "^3.1.2",
- "content-type": "^1.0.5",
- "debug": "^4.4.0",
- "http-errors": "^2.0.0",
- "iconv-lite": "^0.6.3",
- "on-finished": "^2.4.1",
- "qs": "^6.14.0",
- "raw-body": "^3.0.0",
- "type-is": "^2.0.0"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/bowser": {
- "version": "2.12.0",
- "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.12.0.tgz",
- "integrity": "sha512-HcOcTudTeEWgbHh0Y1Tyb6fdeR71m4b/QACf0D4KswGTsNeIJQmg38mRENZPAYPZvGFN3fk3604XbQEPdxXdKg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/brace-expansion": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
- "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0"
- }
- },
- "node_modules/braces": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
- "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "fill-range": "^7.1.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/browser-or-node": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-2.1.1.tgz",
- "integrity": "sha512-8CVjaLJGuSKMVTxJ2DpBl5XnlNDiT4cQFeuCJJrvJmts9YrTZDizTX7PjC2s6W4x+MBGZeEY6dGMrF04/6Hgqg==",
- "license": "MIT"
- },
- "node_modules/browserslist": {
- "version": "4.25.3",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.3.tgz",
- "integrity": "sha512-cDGv1kkDI4/0e5yON9yM5G/0A5u8sf5TnmdX5C9qHzI9PPu++sQ9zjm1k9NiOrf3riY4OkK0zSGqfvJyJsgCBQ==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/browserslist"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "caniuse-lite": "^1.0.30001735",
- "electron-to-chromium": "^1.5.204",
- "node-releases": "^2.0.19",
- "update-browserslist-db": "^1.1.3"
- },
- "bin": {
- "browserslist": "cli.js"
- },
- "engines": {
- "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
- }
- },
- "node_modules/bs-logger": {
- "version": "0.2.6",
- "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz",
- "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "fast-json-stable-stringify": "2.x"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/bser": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
- "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "node-int64": "^0.4.0"
- }
- },
- "node_modules/buffer": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
- "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "base64-js": "^1.3.1",
- "ieee754": "^1.2.1"
- }
- },
- "node_modules/buffer-crc32": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz",
- "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==",
- "license": "MIT",
- "engines": {
- "node": ">=8.0.0"
- }
- },
- "node_modules/buffer-equal-constant-time": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
- "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
- "license": "BSD-3-Clause"
- },
- "node_modules/buffer-from": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
- "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
- "license": "MIT"
- },
- "node_modules/busboy": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
- "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
- "dependencies": {
- "streamsearch": "^1.1.0"
- },
- "engines": {
- "node": ">=10.16.0"
- }
- },
- "node_modules/bytes": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
- "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/call-bind": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
- "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
- "license": "MIT",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.0",
- "es-define-property": "^1.0.0",
- "get-intrinsic": "^1.2.4",
- "set-function-length": "^1.2.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/call-bind-apply-helpers": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
- "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "function-bind": "^1.1.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/call-bound": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
- "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
- "license": "MIT",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.2",
- "get-intrinsic": "^1.3.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/call-me-maybe": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz",
- "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==",
- "license": "MIT"
- },
- "node_modules/callsites": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
- "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/camelcase": {
- "version": "5.3.1",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
- "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/caniuse-lite": {
- "version": "1.0.30001735",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001735.tgz",
- "integrity": "sha512-EV/laoX7Wq2J9TQlyIXRxTJqIw4sxfXS4OYgudGxBYRuTv0q7AM6yMEpU/Vo1I94thg9U6EZ2NfZx9GJq83u7w==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "CC-BY-4.0"
- },
- "node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
- "node_modules/chalk/node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/chalk/node_modules/has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/chalk/node_modules/supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/char-regex": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
- "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/chokidar": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
- "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "anymatch": "~3.1.2",
- "braces": "~3.0.2",
- "glob-parent": "~5.1.2",
- "is-binary-path": "~2.1.0",
- "is-glob": "~4.0.1",
- "normalize-path": "~3.0.0",
- "readdirp": "~3.6.0"
- },
- "engines": {
- "node": ">= 8.10.0"
- },
- "funding": {
- "url": "https://paulmillr.com/funding/"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
- }
- },
- "node_modules/ci-info": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz",
- "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/sibiraj-s"
- }
- ],
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cjs-module-lexer": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.1.0.tgz",
- "integrity": "sha512-UX0OwmYRYQQetfrLEZeewIFFI+wSTofC+pMBLNuH3RUuu/xzG1oz84UCEDOSoQlN3fZ4+AzmV50ZYvGqkMh9yA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/cliui": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
- "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
- "license": "ISC",
- "dependencies": {
- "string-width": "^4.2.0",
- "strip-ansi": "^6.0.1",
- "wrap-ansi": "^7.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/cliui/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cliui/node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "license": "MIT",
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/cliui/node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "license": "MIT"
- },
- "node_modules/cliui/node_modules/string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "license": "MIT",
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cliui/node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cliui/node_modules/wrap-ansi": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
- "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
- }
- },
- "node_modules/cluster-key-slot": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz",
- "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==",
- "license": "Apache-2.0",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/co": {
- "version": "4.6.0",
- "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
- "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "iojs": ">= 1.0.0",
- "node": ">= 0.12.0"
- }
- },
- "node_modules/collect-v8-coverage": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz",
- "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/color": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz",
- "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==",
- "license": "MIT",
- "dependencies": {
- "color-convert": "^1.9.3",
- "color-string": "^1.6.0"
- }
- },
- "node_modules/color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "license": "MIT",
- "dependencies": {
- "color-name": "~1.1.4"
- },
- "engines": {
- "node": ">=7.0.0"
- }
- },
- "node_modules/color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "license": "MIT"
- },
- "node_modules/color-string": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
- "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
- "license": "MIT",
- "dependencies": {
- "color-name": "^1.0.0",
- "simple-swizzle": "^0.2.2"
- }
- },
- "node_modules/color/node_modules/color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "license": "MIT",
- "dependencies": {
- "color-name": "1.1.3"
- }
- },
- "node_modules/color/node_modules/color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
- "license": "MIT"
- },
- "node_modules/colorspace": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz",
- "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==",
- "license": "MIT",
- "dependencies": {
- "color": "^3.1.3",
- "text-hex": "1.0.x"
- }
- },
- "node_modules/combined-stream": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
- "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "delayed-stream": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/commander": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz",
- "integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==",
- "license": "MIT",
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/component-emitter": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz",
- "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==",
- "dev": true,
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
- "license": "MIT"
- },
- "node_modules/concat-stream": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz",
- "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==",
- "engines": [
- "node >= 6.0"
- ],
- "license": "MIT",
- "dependencies": {
- "buffer-from": "^1.0.0",
- "inherits": "^2.0.3",
- "readable-stream": "^3.0.2",
- "typedarray": "^0.0.6"
- }
- },
- "node_modules/content-disposition": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz",
- "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==",
- "license": "MIT",
- "dependencies": {
- "safe-buffer": "5.2.1"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/content-type": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
- "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/convert-source-map": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
- "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/cookie": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
- "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/cookie-parser": {
- "version": "1.4.7",
- "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz",
- "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==",
- "license": "MIT",
- "dependencies": {
- "cookie": "0.7.2",
- "cookie-signature": "1.0.6"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/cookie-signature": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
- "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
- "license": "MIT"
- },
- "node_modules/cookiejar": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz",
- "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/cors": {
- "version": "2.8.5",
- "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
- "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
- "license": "MIT",
- "dependencies": {
- "object-assign": "^4",
- "vary": "^1"
- },
- "engines": {
- "node": ">= 0.10"
- }
- },
- "node_modules/create-require": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
- "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
- "devOptional": true,
- "license": "MIT"
- },
- "node_modules/cross-spawn": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
- "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
- "license": "MIT",
- "dependencies": {
- "path-key": "^3.1.0",
- "shebang-command": "^2.0.0",
- "which": "^2.0.1"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/dayjs": {
- "version": "1.11.13",
- "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
- "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==",
- "license": "MIT"
- },
- "node_modules/debug": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
- "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/decode-uri-component": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz",
- "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10"
- }
- },
- "node_modules/dedent": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.6.0.tgz",
- "integrity": "sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==",
- "license": "MIT",
- "peerDependencies": {
- "babel-plugin-macros": "^3.1.0"
- },
- "peerDependenciesMeta": {
- "babel-plugin-macros": {
- "optional": true
- }
- }
- },
- "node_modules/deepmerge": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
- "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/define-data-property": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
- "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
- "license": "MIT",
- "dependencies": {
- "es-define-property": "^1.0.0",
- "es-errors": "^1.3.0",
- "gopd": "^1.0.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/delayed-stream": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
- "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/depd": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
- "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/detect-libc": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
- "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
- "license": "Apache-2.0",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/detect-newline": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
- "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/dezalgo": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz",
- "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "asap": "^2.0.0",
- "wrappy": "1"
- }
- },
- "node_modules/diff": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
- "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
- "devOptional": true,
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=0.3.1"
- }
- },
- "node_modules/doctrine": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
- "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
- "license": "Apache-2.0",
- "dependencies": {
- "esutils": "^2.0.2"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/dotenv": {
- "version": "16.6.1",
- "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
- "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
- "license": "BSD-2-Clause",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://dotenvx.com"
- }
- },
- "node_modules/dunder-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
- "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
- "license": "MIT",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.1",
- "es-errors": "^1.3.0",
- "gopd": "^1.2.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/eastasianwidth": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
- "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
- "license": "MIT"
- },
- "node_modules/ecdsa-sig-formatter": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
- "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "safe-buffer": "^5.0.1"
- }
- },
- "node_modules/ee-first": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
- "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
- "license": "MIT"
- },
- "node_modules/electron-to-chromium": {
- "version": "1.5.207",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.207.tgz",
- "integrity": "sha512-mryFrrL/GXDTmAtIVMVf+eIXM09BBPlO5IQ7lUyKmK8d+A4VpRGG+M3ofoVef6qyF8s60rJei8ymlJxjUA8Faw==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/emittery": {
- "version": "0.13.1",
- "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz",
- "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sindresorhus/emittery?sponsor=1"
- }
- },
- "node_modules/emoji-regex": {
- "version": "9.2.2",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
- "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
- "license": "MIT"
- },
- "node_modules/enabled": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz",
- "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==",
- "license": "MIT"
- },
- "node_modules/encodeurl": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
- "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/engine.io": {
- "version": "6.6.4",
- "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.4.tgz",
- "integrity": "sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==",
- "license": "MIT",
- "dependencies": {
- "@types/cors": "^2.8.12",
- "@types/node": ">=10.0.0",
- "accepts": "~1.3.4",
- "base64id": "2.0.0",
- "cookie": "~0.7.2",
- "cors": "~2.8.5",
- "debug": "~4.3.1",
- "engine.io-parser": "~5.2.1",
- "ws": "~8.17.1"
- },
- "engines": {
- "node": ">=10.2.0"
- }
- },
- "node_modules/engine.io-client": {
- "version": "6.6.3",
- "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz",
- "integrity": "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@socket.io/component-emitter": "~3.1.0",
- "debug": "~4.3.1",
- "engine.io-parser": "~5.2.1",
- "ws": "~8.17.1",
- "xmlhttprequest-ssl": "~2.1.1"
- }
- },
- "node_modules/engine.io-client/node_modules/debug": {
- "version": "4.3.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
- "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/engine.io-parser": {
- "version": "5.2.3",
- "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz",
- "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==",
- "license": "MIT",
- "engines": {
- "node": ">=10.0.0"
- }
- },
- "node_modules/engine.io/node_modules/accepts": {
- "version": "1.3.8",
- "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
- "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
- "license": "MIT",
- "dependencies": {
- "mime-types": "~2.1.34",
- "negotiator": "0.6.3"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/engine.io/node_modules/debug": {
- "version": "4.3.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
- "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/engine.io/node_modules/mime-db": {
- "version": "1.52.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
- "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/engine.io/node_modules/mime-types": {
- "version": "2.1.35",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
- "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
- "license": "MIT",
- "dependencies": {
- "mime-db": "1.52.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/engine.io/node_modules/negotiator": {
- "version": "0.6.3",
- "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
- "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/error-ex": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
- "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-arrayish": "^0.2.1"
- }
- },
- "node_modules/error-ex/node_modules/is-arrayish": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
- "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/es-define-property": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
- "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-errors": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
- "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-object-atoms": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
- "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-set-tostringtag": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
- "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.6",
- "has-tostringtag": "^1.0.2",
- "hasown": "^2.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/escalade": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
- "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/escape-html": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
- "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
- "license": "MIT"
- },
- "node_modules/escape-string-regexp": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
- "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/esprima": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
- "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
- "dev": true,
- "license": "BSD-2-Clause",
- "bin": {
- "esparse": "bin/esparse.js",
- "esvalidate": "bin/esvalidate.js"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/esutils": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
- "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
- "license": "BSD-2-Clause",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/etag": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
- "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/eventemitter3": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
- "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
- "license": "MIT"
- },
- "node_modules/execa": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
- "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "cross-spawn": "^7.0.3",
- "get-stream": "^6.0.0",
- "human-signals": "^2.1.0",
- "is-stream": "^2.0.0",
- "merge-stream": "^2.0.0",
- "npm-run-path": "^4.0.1",
- "onetime": "^5.1.2",
- "signal-exit": "^3.0.3",
- "strip-final-newline": "^2.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sindresorhus/execa?sponsor=1"
- }
- },
- "node_modules/execa/node_modules/signal-exit": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
- "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/exit-x": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/exit-x/-/exit-x-0.2.2.tgz",
- "integrity": "sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/expect": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/expect/-/expect-30.0.5.tgz",
- "integrity": "sha512-P0te2pt+hHI5qLJkIR+iMvS+lYUZml8rKKsohVHAGY+uClp9XVbdyYNJOIjSRpHVp8s8YqxJCiHUkSYZGr8rtQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/expect-utils": "30.0.5",
- "@jest/get-type": "30.0.1",
- "jest-matcher-utils": "30.0.5",
- "jest-message-util": "30.0.5",
- "jest-mock": "30.0.5",
- "jest-util": "30.0.5"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/express": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz",
- "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==",
- "license": "MIT",
- "dependencies": {
- "accepts": "^2.0.0",
- "body-parser": "^2.2.0",
- "content-disposition": "^1.0.0",
- "content-type": "^1.0.5",
- "cookie": "^0.7.1",
- "cookie-signature": "^1.2.1",
- "debug": "^4.4.0",
- "encodeurl": "^2.0.0",
- "escape-html": "^1.0.3",
- "etag": "^1.8.1",
- "finalhandler": "^2.1.0",
- "fresh": "^2.0.0",
- "http-errors": "^2.0.0",
- "merge-descriptors": "^2.0.0",
- "mime-types": "^3.0.0",
- "on-finished": "^2.4.1",
- "once": "^1.4.0",
- "parseurl": "^1.3.3",
- "proxy-addr": "^2.0.7",
- "qs": "^6.14.0",
- "range-parser": "^1.2.1",
- "router": "^2.2.0",
- "send": "^1.1.0",
- "serve-static": "^2.2.0",
- "statuses": "^2.0.1",
- "type-is": "^2.0.1",
- "vary": "^1.1.2"
- },
- "engines": {
- "node": ">= 18"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/express/node_modules/cookie-signature": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
- "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
- "license": "MIT",
- "engines": {
- "node": ">=6.6.0"
- }
- },
- "node_modules/fast-json-stable-stringify": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
- "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/fast-safe-stringify": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
- "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/fast-xml-parser": {
- "version": "5.2.5",
- "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.2.5.tgz",
- "integrity": "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/NaturalIntelligence"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "strnum": "^2.1.0"
- },
- "bin": {
- "fxparser": "src/cli/cli.js"
- }
- },
- "node_modules/fb-watchman": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
- "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "bser": "2.1.1"
- }
- },
- "node_modules/fecha": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz",
- "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==",
- "license": "MIT"
- },
- "node_modules/fill-range": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
- "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "to-regex-range": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/filter-obj": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz",
- "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/finalhandler": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz",
- "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==",
- "license": "MIT",
- "dependencies": {
- "debug": "^4.4.0",
- "encodeurl": "^2.0.0",
- "escape-html": "^1.0.3",
- "on-finished": "^2.4.1",
- "parseurl": "^1.3.3",
- "statuses": "^2.0.1"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/find-up": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
- "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "locate-path": "^5.0.0",
- "path-exists": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/fn.name": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz",
- "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==",
- "license": "MIT"
- },
- "node_modules/for-each": {
- "version": "0.3.5",
- "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
- "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
- "license": "MIT",
- "dependencies": {
- "is-callable": "^1.2.7"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/foreground-child": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
- "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
- "license": "ISC",
- "dependencies": {
- "cross-spawn": "^7.0.6",
- "signal-exit": "^4.0.1"
- },
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/form-data": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
- "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "asynckit": "^0.4.0",
- "combined-stream": "^1.0.8",
- "es-set-tostringtag": "^2.1.0",
- "hasown": "^2.0.2",
- "mime-types": "^2.1.12"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/form-data/node_modules/mime-db": {
- "version": "1.52.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
- "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/form-data/node_modules/mime-types": {
- "version": "2.1.35",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
- "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "mime-db": "1.52.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/formidable": {
- "version": "3.5.4",
- "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.4.tgz",
- "integrity": "sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@paralleldrive/cuid2": "^2.2.2",
- "dezalgo": "^1.0.4",
- "once": "^1.4.0"
- },
- "engines": {
- "node": ">=14.0.0"
- },
- "funding": {
- "url": "https://ko-fi.com/tunnckoCore/commissions"
- }
- },
- "node_modules/forwarded": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
- "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/fresh": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
- "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
- "license": "ISC"
- },
- "node_modules/fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "dev": true,
- "hasInstallScript": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
- "node_modules/function-bind": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
- "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/gensync": {
- "version": "1.0.0-beta.2",
- "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
- "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/get-caller-file": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
- "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
- "license": "ISC",
- "engines": {
- "node": "6.* || 8.* || >= 10.*"
- }
- },
- "node_modules/get-intrinsic": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
- "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
- "license": "MIT",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.2",
- "es-define-property": "^1.0.1",
- "es-errors": "^1.3.0",
- "es-object-atoms": "^1.1.1",
- "function-bind": "^1.1.2",
- "get-proto": "^1.0.1",
- "gopd": "^1.2.0",
- "has-symbols": "^1.1.0",
- "hasown": "^2.0.2",
- "math-intrinsics": "^1.1.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/get-package-type": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
- "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8.0.0"
- }
- },
- "node_modules/get-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
- "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
- "license": "MIT",
- "dependencies": {
- "dunder-proto": "^1.0.1",
- "es-object-atoms": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/get-stream": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
- "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/glob": {
- "version": "10.4.5",
- "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
- "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
- "license": "ISC",
- "dependencies": {
- "foreground-child": "^3.1.0",
- "jackspeak": "^3.1.2",
- "minimatch": "^9.0.4",
- "minipass": "^7.1.2",
- "package-json-from-dist": "^1.0.0",
- "path-scurry": "^1.11.1"
- },
- "bin": {
- "glob": "dist/esm/bin.mjs"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "is-glob": "^4.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/gopd": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
- "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/graceful-fs": {
- "version": "4.2.11",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
- "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/handlebars": {
- "version": "4.7.8",
- "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz",
- "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "minimist": "^1.2.5",
- "neo-async": "^2.6.2",
- "source-map": "^0.6.1",
- "wordwrap": "^1.0.0"
- },
- "bin": {
- "handlebars": "bin/handlebars"
- },
- "engines": {
- "node": ">=0.4.7"
- },
- "optionalDependencies": {
- "uglify-js": "^3.1.4"
- }
- },
- "node_modules/has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/has-property-descriptors": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
- "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
- "license": "MIT",
- "dependencies": {
- "es-define-property": "^1.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-symbols": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
- "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-tostringtag": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
- "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
- "license": "MIT",
- "dependencies": {
- "has-symbols": "^1.0.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/hasown": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
- "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
- "license": "MIT",
- "dependencies": {
- "function-bind": "^1.1.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/helmet": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/helmet/-/helmet-8.1.0.tgz",
- "integrity": "sha512-jOiHyAZsmnr8LqoPGmCjYAaiuWwjAPLgY8ZX2XrmHawt99/u1y6RgrZMTeoPfpUbV96HOalYgz1qzkRbw54Pmg==",
- "license": "MIT",
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/html-escaper": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
- "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/http-errors": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
- "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
- "license": "MIT",
- "dependencies": {
- "depd": "2.0.0",
- "inherits": "2.0.4",
- "setprototypeof": "1.2.0",
- "statuses": "2.0.1",
- "toidentifier": "1.0.1"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/http-errors/node_modules/statuses": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
- "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/human-signals": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
- "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": ">=10.17.0"
- }
- },
- "node_modules/iconv-lite": {
- "version": "0.6.3",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
- "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
- "license": "MIT",
- "dependencies": {
- "safer-buffer": ">= 2.1.2 < 3.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/ieee754": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
- "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "BSD-3-Clause"
- },
- "node_modules/ignore-by-default": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
- "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/import-local": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz",
- "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "pkg-dir": "^4.2.0",
- "resolve-cwd": "^3.0.0"
- },
- "bin": {
- "import-local-fixture": "fixtures/cli.js"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/imurmurhash": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.8.19"
- }
- },
- "node_modules/inflight": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
- "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
- "license": "ISC",
- "dependencies": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
- "node_modules/inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "license": "ISC"
- },
- "node_modules/ipaddr.js": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
- "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.10"
- }
- },
- "node_modules/is-arguments": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz",
- "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.2",
- "has-tostringtag": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-arrayish": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
- "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
- "license": "MIT"
- },
- "node_modules/is-binary-path": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
- "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "binary-extensions": "^2.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-callable": {
- "version": "1.2.7",
- "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
- "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-extglob": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-generator-fn": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz",
- "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/is-generator-function": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz",
- "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3",
- "get-proto": "^1.0.0",
- "has-tostringtag": "^1.0.2",
- "safe-regex-test": "^1.1.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-glob": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
- "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-extglob": "^2.1.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-number": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.12.0"
- }
- },
- "node_modules/is-promise": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
- "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
- "license": "MIT"
- },
- "node_modules/is-regex": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
- "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.2",
- "gopd": "^1.2.0",
- "has-tostringtag": "^1.0.2",
- "hasown": "^2.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-stream": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
- "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/is-typed-array": {
- "version": "1.1.15",
- "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
- "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
- "license": "MIT",
- "dependencies": {
- "which-typed-array": "^1.1.16"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/isarray": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
- "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
- "license": "MIT"
- },
- "node_modules/isexe": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "license": "ISC"
- },
- "node_modules/istanbul-lib-coverage": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
- "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
- "dev": true,
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/istanbul-lib-instrument": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz",
- "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "@babel/core": "^7.23.9",
- "@babel/parser": "^7.23.9",
- "@istanbuljs/schema": "^0.1.3",
- "istanbul-lib-coverage": "^3.2.0",
- "semver": "^7.5.4"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/istanbul-lib-report": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
- "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "istanbul-lib-coverage": "^3.0.0",
- "make-dir": "^4.0.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/istanbul-lib-report/node_modules/has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/istanbul-lib-report/node_modules/supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/istanbul-lib-source-maps": {
- "version": "5.0.6",
- "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz",
- "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "@jridgewell/trace-mapping": "^0.3.23",
- "debug": "^4.1.1",
- "istanbul-lib-coverage": "^3.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/istanbul-lib-source-maps/node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.30",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz",
- "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
- }
- },
- "node_modules/istanbul-reports": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz",
- "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "html-escaper": "^2.0.0",
- "istanbul-lib-report": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/jackspeak": {
- "version": "3.4.3",
- "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
- "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "@isaacs/cliui": "^8.0.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- },
- "optionalDependencies": {
- "@pkgjs/parseargs": "^0.11.0"
- }
- },
- "node_modules/jest": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/jest/-/jest-30.0.5.tgz",
- "integrity": "sha512-y2mfcJywuTUkvLm2Lp1/pFX8kTgMO5yyQGq/Sk/n2mN7XWYp4JsCZ/QXW34M8YScgk8bPZlREH04f6blPnoHnQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/core": "30.0.5",
- "@jest/types": "30.0.5",
- "import-local": "^3.2.0",
- "jest-cli": "30.0.5"
- },
- "bin": {
- "jest": "bin/jest.js"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- },
- "peerDependencies": {
- "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
- },
- "peerDependenciesMeta": {
- "node-notifier": {
- "optional": true
- }
- }
- },
- "node_modules/jest-changed-files": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.0.5.tgz",
- "integrity": "sha512-bGl2Ntdx0eAwXuGpdLdVYVr5YQHnSZlQ0y9HVDu565lCUAe9sj6JOtBbMmBBikGIegne9piDDIOeiLVoqTkz4A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "execa": "^5.1.1",
- "jest-util": "30.0.5",
- "p-limit": "^3.1.0"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/jest-circus": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.0.5.tgz",
- "integrity": "sha512-h/sjXEs4GS+NFFfqBDYT7y5Msfxh04EwWLhQi0F8kuWpe+J/7tICSlswU8qvBqumR3kFgHbfu7vU6qruWWBPug==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/environment": "30.0.5",
- "@jest/expect": "30.0.5",
- "@jest/test-result": "30.0.5",
- "@jest/types": "30.0.5",
- "@types/node": "*",
- "chalk": "^4.1.2",
- "co": "^4.6.0",
- "dedent": "^1.6.0",
- "is-generator-fn": "^2.1.0",
- "jest-each": "30.0.5",
- "jest-matcher-utils": "30.0.5",
- "jest-message-util": "30.0.5",
- "jest-runtime": "30.0.5",
- "jest-snapshot": "30.0.5",
- "jest-util": "30.0.5",
- "p-limit": "^3.1.0",
- "pretty-format": "30.0.5",
- "pure-rand": "^7.0.0",
- "slash": "^3.0.0",
- "stack-utils": "^2.0.6"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/jest-cli": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.0.5.tgz",
- "integrity": "sha512-Sa45PGMkBZzF94HMrlX4kUyPOwUpdZasaliKN3mifvDmkhLYqLLg8HQTzn6gq7vJGahFYMQjXgyJWfYImKZzOw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/core": "30.0.5",
- "@jest/test-result": "30.0.5",
- "@jest/types": "30.0.5",
- "chalk": "^4.1.2",
- "exit-x": "^0.2.2",
- "import-local": "^3.2.0",
- "jest-config": "30.0.5",
- "jest-util": "30.0.5",
- "jest-validate": "30.0.5",
- "yargs": "^17.7.2"
- },
- "bin": {
- "jest": "bin/jest.js"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- },
- "peerDependencies": {
- "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
- },
- "peerDependenciesMeta": {
- "node-notifier": {
- "optional": true
- }
- }
- },
- "node_modules/jest-config": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.0.5.tgz",
- "integrity": "sha512-aIVh+JNOOpzUgzUnPn5FLtyVnqc3TQHVMupYtyeURSb//iLColiMIR8TxCIDKyx9ZgjKnXGucuW68hCxgbrwmA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/core": "^7.27.4",
- "@jest/get-type": "30.0.1",
- "@jest/pattern": "30.0.1",
- "@jest/test-sequencer": "30.0.5",
- "@jest/types": "30.0.5",
- "babel-jest": "30.0.5",
- "chalk": "^4.1.2",
- "ci-info": "^4.2.0",
- "deepmerge": "^4.3.1",
- "glob": "^10.3.10",
- "graceful-fs": "^4.2.11",
- "jest-circus": "30.0.5",
- "jest-docblock": "30.0.1",
- "jest-environment-node": "30.0.5",
- "jest-regex-util": "30.0.1",
- "jest-resolve": "30.0.5",
- "jest-runner": "30.0.5",
- "jest-util": "30.0.5",
- "jest-validate": "30.0.5",
- "micromatch": "^4.0.8",
- "parse-json": "^5.2.0",
- "pretty-format": "30.0.5",
- "slash": "^3.0.0",
- "strip-json-comments": "^3.1.1"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- },
- "peerDependencies": {
- "@types/node": "*",
- "esbuild-register": ">=3.4.0",
- "ts-node": ">=9.0.0"
- },
- "peerDependenciesMeta": {
- "@types/node": {
- "optional": true
- },
- "esbuild-register": {
- "optional": true
- },
- "ts-node": {
- "optional": true
- }
- }
- },
- "node_modules/jest-diff": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.0.5.tgz",
- "integrity": "sha512-1UIqE9PoEKaHcIKvq2vbibrCog4Y8G0zmOxgQUVEiTqwR5hJVMCoDsN1vFvI5JvwD37hjueZ1C4l2FyGnfpE0A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/diff-sequences": "30.0.1",
- "@jest/get-type": "30.0.1",
- "chalk": "^4.1.2",
- "pretty-format": "30.0.5"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/jest-docblock": {
- "version": "30.0.1",
- "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-30.0.1.tgz",
- "integrity": "sha512-/vF78qn3DYphAaIc3jy4gA7XSAz167n9Bm/wn/1XhTLW7tTBIzXtCJpb/vcmc73NIIeeohCbdL94JasyXUZsGA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "detect-newline": "^3.1.0"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/jest-each": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.0.5.tgz",
- "integrity": "sha512-dKjRsx1uZ96TVyejD3/aAWcNKy6ajMaN531CwWIsrazIqIoXI9TnnpPlkrEYku/8rkS3dh2rbH+kMOyiEIv0xQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/get-type": "30.0.1",
- "@jest/types": "30.0.5",
- "chalk": "^4.1.2",
- "jest-util": "30.0.5",
- "pretty-format": "30.0.5"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/jest-environment-node": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.0.5.tgz",
- "integrity": "sha512-ppYizXdLMSvciGsRsMEnv/5EFpvOdXBaXRBzFUDPWrsfmog4kYrOGWXarLllz6AXan6ZAA/kYokgDWuos1IKDA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/environment": "30.0.5",
- "@jest/fake-timers": "30.0.5",
- "@jest/types": "30.0.5",
- "@types/node": "*",
- "jest-mock": "30.0.5",
- "jest-util": "30.0.5",
- "jest-validate": "30.0.5"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/jest-haste-map": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.0.5.tgz",
- "integrity": "sha512-dkmlWNlsTSR0nH3nRfW5BKbqHefLZv0/6LCccG0xFCTWcJu8TuEwG+5Cm75iBfjVoockmO6J35o5gxtFSn5xeg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/types": "30.0.5",
- "@types/node": "*",
- "anymatch": "^3.1.3",
- "fb-watchman": "^2.0.2",
- "graceful-fs": "^4.2.11",
- "jest-regex-util": "30.0.1",
- "jest-util": "30.0.5",
- "jest-worker": "30.0.5",
- "micromatch": "^4.0.8",
- "walker": "^1.0.8"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- },
- "optionalDependencies": {
- "fsevents": "^2.3.3"
- }
- },
- "node_modules/jest-leak-detector": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.0.5.tgz",
- "integrity": "sha512-3Uxr5uP8jmHMcsOtYMRB/zf1gXN3yUIc+iPorhNETG54gErFIiUhLvyY/OggYpSMOEYqsmRxmuU4ZOoX5jpRFg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/get-type": "30.0.1",
- "pretty-format": "30.0.5"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/jest-matcher-utils": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.0.5.tgz",
- "integrity": "sha512-uQgGWt7GOrRLP1P7IwNWwK1WAQbq+m//ZY0yXygyfWp0rJlksMSLQAA4wYQC3b6wl3zfnchyTx+k3HZ5aPtCbQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/get-type": "30.0.1",
- "chalk": "^4.1.2",
- "jest-diff": "30.0.5",
- "pretty-format": "30.0.5"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/jest-message-util": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.0.5.tgz",
- "integrity": "sha512-NAiDOhsK3V7RU0Aa/HnrQo+E4JlbarbmI3q6Pi4KcxicdtjV82gcIUrejOtczChtVQR4kddu1E1EJlW6EN9IyA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.27.1",
- "@jest/types": "30.0.5",
- "@types/stack-utils": "^2.0.3",
- "chalk": "^4.1.2",
- "graceful-fs": "^4.2.11",
- "micromatch": "^4.0.8",
- "pretty-format": "30.0.5",
- "slash": "^3.0.0",
- "stack-utils": "^2.0.6"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/jest-mock": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.0.5.tgz",
- "integrity": "sha512-Od7TyasAAQX/6S+QCbN6vZoWOMwlTtzzGuxJku1GhGanAjz9y+QsQkpScDmETvdc9aSXyJ/Op4rhpMYBWW91wQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/types": "30.0.5",
- "@types/node": "*",
- "jest-util": "30.0.5"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/jest-pnp-resolver": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz",
- "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- },
- "peerDependencies": {
- "jest-resolve": "*"
- },
- "peerDependenciesMeta": {
- "jest-resolve": {
- "optional": true
- }
- }
- },
- "node_modules/jest-regex-util": {
- "version": "30.0.1",
- "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz",
- "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/jest-resolve": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.0.5.tgz",
- "integrity": "sha512-d+DjBQ1tIhdz91B79mywH5yYu76bZuE96sSbxj8MkjWVx5WNdt1deEFRONVL4UkKLSrAbMkdhb24XN691yDRHg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "chalk": "^4.1.2",
- "graceful-fs": "^4.2.11",
- "jest-haste-map": "30.0.5",
- "jest-pnp-resolver": "^1.2.3",
- "jest-util": "30.0.5",
- "jest-validate": "30.0.5",
- "slash": "^3.0.0",
- "unrs-resolver": "^1.7.11"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/jest-resolve-dependencies": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.0.5.tgz",
- "integrity": "sha512-/xMvBR4MpwkrHW4ikZIWRttBBRZgWK4d6xt3xW1iRDSKt4tXzYkMkyPfBnSCgv96cpkrctfXs6gexeqMYqdEpw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "jest-regex-util": "30.0.1",
- "jest-snapshot": "30.0.5"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/jest-runner": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.0.5.tgz",
- "integrity": "sha512-JcCOucZmgp+YuGgLAXHNy7ualBx4wYSgJVWrYMRBnb79j9PD0Jxh0EHvR5Cx/r0Ce+ZBC4hCdz2AzFFLl9hCiw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/console": "30.0.5",
- "@jest/environment": "30.0.5",
- "@jest/test-result": "30.0.5",
- "@jest/transform": "30.0.5",
- "@jest/types": "30.0.5",
- "@types/node": "*",
- "chalk": "^4.1.2",
- "emittery": "^0.13.1",
- "exit-x": "^0.2.2",
- "graceful-fs": "^4.2.11",
- "jest-docblock": "30.0.1",
- "jest-environment-node": "30.0.5",
- "jest-haste-map": "30.0.5",
- "jest-leak-detector": "30.0.5",
- "jest-message-util": "30.0.5",
- "jest-resolve": "30.0.5",
- "jest-runtime": "30.0.5",
- "jest-util": "30.0.5",
- "jest-watcher": "30.0.5",
- "jest-worker": "30.0.5",
- "p-limit": "^3.1.0",
- "source-map-support": "0.5.13"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/jest-runtime": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.0.5.tgz",
- "integrity": "sha512-7oySNDkqpe4xpX5PPiJTe5vEa+Ak/NnNz2bGYZrA1ftG3RL3EFlHaUkA1Cjx+R8IhK0Vg43RML5mJedGTPNz3A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/environment": "30.0.5",
- "@jest/fake-timers": "30.0.5",
- "@jest/globals": "30.0.5",
- "@jest/source-map": "30.0.1",
- "@jest/test-result": "30.0.5",
- "@jest/transform": "30.0.5",
- "@jest/types": "30.0.5",
- "@types/node": "*",
- "chalk": "^4.1.2",
- "cjs-module-lexer": "^2.1.0",
- "collect-v8-coverage": "^1.0.2",
- "glob": "^10.3.10",
- "graceful-fs": "^4.2.11",
- "jest-haste-map": "30.0.5",
- "jest-message-util": "30.0.5",
- "jest-mock": "30.0.5",
- "jest-regex-util": "30.0.1",
- "jest-resolve": "30.0.5",
- "jest-snapshot": "30.0.5",
- "jest-util": "30.0.5",
- "slash": "^3.0.0",
- "strip-bom": "^4.0.0"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/jest-runtime/node_modules/strip-bom": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
- "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/jest-snapshot": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.0.5.tgz",
- "integrity": "sha512-T00dWU/Ek3LqTp4+DcW6PraVxjk28WY5Ua/s+3zUKSERZSNyxTqhDXCWKG5p2HAJ+crVQ3WJ2P9YVHpj1tkW+g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/core": "^7.27.4",
- "@babel/generator": "^7.27.5",
- "@babel/plugin-syntax-jsx": "^7.27.1",
- "@babel/plugin-syntax-typescript": "^7.27.1",
- "@babel/types": "^7.27.3",
- "@jest/expect-utils": "30.0.5",
- "@jest/get-type": "30.0.1",
- "@jest/snapshot-utils": "30.0.5",
- "@jest/transform": "30.0.5",
- "@jest/types": "30.0.5",
- "babel-preset-current-node-syntax": "^1.1.0",
- "chalk": "^4.1.2",
- "expect": "30.0.5",
- "graceful-fs": "^4.2.11",
- "jest-diff": "30.0.5",
- "jest-matcher-utils": "30.0.5",
- "jest-message-util": "30.0.5",
- "jest-util": "30.0.5",
- "pretty-format": "30.0.5",
- "semver": "^7.7.2",
- "synckit": "^0.11.8"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/jest-util": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.0.5.tgz",
- "integrity": "sha512-pvyPWssDZR0FlfMxCBoc0tvM8iUEskaRFALUtGQYzVEAqisAztmy+R8LnU14KT4XA0H/a5HMVTXat1jLne010g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/types": "30.0.5",
- "@types/node": "*",
- "chalk": "^4.1.2",
- "ci-info": "^4.2.0",
- "graceful-fs": "^4.2.11",
- "picomatch": "^4.0.2"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/jest-util/node_modules/picomatch": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
- "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/jest-validate": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.0.5.tgz",
- "integrity": "sha512-ouTm6VFHaS2boyl+k4u+Qip4TSH7Uld5tyD8psQ8abGgt2uYYB8VwVfAHWHjHc0NWmGGbwO5h0sCPOGHHevefw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/get-type": "30.0.1",
- "@jest/types": "30.0.5",
- "camelcase": "^6.3.0",
- "chalk": "^4.1.2",
- "leven": "^3.1.0",
- "pretty-format": "30.0.5"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/jest-validate/node_modules/camelcase": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
- "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/jest-watcher": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.0.5.tgz",
- "integrity": "sha512-z9slj/0vOwBDBjN3L4z4ZYaA+pG56d6p3kTUhFRYGvXbXMWhXmb/FIxREZCD06DYUwDKKnj2T80+Pb71CQ0KEg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/test-result": "30.0.5",
- "@jest/types": "30.0.5",
- "@types/node": "*",
- "ansi-escapes": "^4.3.2",
- "chalk": "^4.1.2",
- "emittery": "^0.13.1",
- "jest-util": "30.0.5",
- "string-length": "^4.0.2"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/jest-worker": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.0.5.tgz",
- "integrity": "sha512-ojRXsWzEP16NdUuBw/4H/zkZdHOa7MMYCk4E430l+8fELeLg/mqmMlRhjL7UNZvQrDmnovWZV4DxX03fZF48fQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "*",
- "@ungap/structured-clone": "^1.3.0",
- "jest-util": "30.0.5",
- "merge-stream": "^2.0.0",
- "supports-color": "^8.1.1"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/jest-worker/node_modules/has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/jest-worker/node_modules/supports-color": {
- "version": "8.1.1",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
- "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/supports-color?sponsor=1"
- }
- },
- "node_modules/js-tokens": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
- "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
- "license": "MIT",
- "dependencies": {
- "argparse": "^2.0.1"
- },
- "bin": {
- "js-yaml": "bin/js-yaml.js"
- }
- },
- "node_modules/jsesc": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
- "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "jsesc": "bin/jsesc"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/json-parse-even-better-errors": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
- "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/json5": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
- "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
- "license": "MIT",
- "bin": {
- "json5": "lib/cli.js"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/jsonwebtoken": {
- "version": "9.0.2",
- "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz",
- "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==",
- "license": "MIT",
- "dependencies": {
- "jws": "^3.2.2",
- "lodash.includes": "^4.3.0",
- "lodash.isboolean": "^3.0.3",
- "lodash.isinteger": "^4.0.4",
- "lodash.isnumber": "^3.0.3",
- "lodash.isplainobject": "^4.0.6",
- "lodash.isstring": "^4.0.1",
- "lodash.once": "^4.0.0",
- "ms": "^2.1.1",
- "semver": "^7.5.4"
- },
- "engines": {
- "node": ">=12",
- "npm": ">=6"
- }
- },
- "node_modules/jwa": {
- "version": "1.4.2",
- "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz",
- "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==",
- "license": "MIT",
- "dependencies": {
- "buffer-equal-constant-time": "^1.0.1",
- "ecdsa-sig-formatter": "1.0.11",
- "safe-buffer": "^5.0.1"
- }
- },
- "node_modules/jws": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
- "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
- "license": "MIT",
- "dependencies": {
- "jwa": "^1.4.1",
- "safe-buffer": "^5.0.1"
- }
- },
- "node_modules/kuler": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz",
- "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==",
- "license": "MIT"
- },
- "node_modules/leven": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
- "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/lines-and-columns": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
- "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/locate-path": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
- "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "p-locate": "^4.1.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/lodash": {
- "version": "4.17.21",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
- "license": "MIT"
- },
- "node_modules/lodash.get": {
- "version": "4.4.2",
- "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
- "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==",
- "deprecated": "This package is deprecated. Use the optional chaining (?.) operator instead.",
- "license": "MIT"
- },
- "node_modules/lodash.includes": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
- "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==",
- "license": "MIT"
- },
- "node_modules/lodash.isboolean": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
- "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==",
- "license": "MIT"
- },
- "node_modules/lodash.isequal": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
- "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
- "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.",
- "license": "MIT"
- },
- "node_modules/lodash.isinteger": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
- "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==",
- "license": "MIT"
- },
- "node_modules/lodash.isnumber": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
- "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==",
- "license": "MIT"
- },
- "node_modules/lodash.isplainobject": {
- "version": "4.0.6",
- "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
- "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
- "license": "MIT"
- },
- "node_modules/lodash.isstring": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
- "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==",
- "license": "MIT"
- },
- "node_modules/lodash.memoize": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
- "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/lodash.mergewith": {
- "version": "4.6.2",
- "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz",
- "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==",
- "license": "MIT"
- },
- "node_modules/lodash.once": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
- "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==",
- "license": "MIT"
- },
- "node_modules/logform": {
- "version": "2.7.0",
- "resolved": "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz",
- "integrity": "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==",
- "license": "MIT",
- "dependencies": {
- "@colors/colors": "1.6.0",
- "@types/triple-beam": "^1.3.2",
- "fecha": "^4.2.0",
- "ms": "^2.1.1",
- "safe-stable-stringify": "^2.3.1",
- "triple-beam": "^1.3.0"
- },
- "engines": {
- "node": ">= 12.0.0"
- }
- },
- "node_modules/lru-cache": {
- "version": "10.4.3",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
- "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
- "license": "ISC"
- },
- "node_modules/make-dir": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
- "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "semver": "^7.5.3"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/make-error": {
- "version": "1.3.6",
- "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
- "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
- "devOptional": true,
- "license": "ISC"
- },
- "node_modules/makeerror": {
- "version": "1.0.12",
- "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
- "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "tmpl": "1.0.5"
- }
- },
- "node_modules/math-intrinsics": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
- "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/media-typer": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz",
- "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/merge-descriptors": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz",
- "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/merge-stream": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
- "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/methods": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
- "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/micromatch": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
- "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "braces": "^3.0.3",
- "picomatch": "^2.3.1"
- },
- "engines": {
- "node": ">=8.6"
- }
- },
- "node_modules/mime": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
- "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "mime": "cli.js"
- },
- "engines": {
- "node": ">=4.0.0"
- }
- },
- "node_modules/mime-db": {
- "version": "1.54.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
- "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mime-types": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz",
- "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
- "license": "MIT",
- "dependencies": {
- "mime-db": "^1.54.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mimic-fn": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
- "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/minimatch": {
- "version": "9.0.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
- "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^2.0.1"
- },
- "engines": {
- "node": ">=16 || 14 >=14.17"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/minimist": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
- "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/minio": {
- "version": "8.0.5",
- "resolved": "https://registry.npmjs.org/minio/-/minio-8.0.5.tgz",
- "integrity": "sha512-/vAze1uyrK2R/DSkVutE4cjVoAowvIQ18RAwn7HrqnLecLlMazFnY0oNBqfuoAWvu7mZIGX75AzpuV05TJeoHg==",
- "license": "Apache-2.0",
- "dependencies": {
- "async": "^3.2.4",
- "block-stream2": "^2.1.0",
- "browser-or-node": "^2.1.1",
- "buffer-crc32": "^1.0.0",
- "eventemitter3": "^5.0.1",
- "fast-xml-parser": "^4.4.1",
- "ipaddr.js": "^2.0.1",
- "lodash": "^4.17.21",
- "mime-types": "^2.1.35",
- "query-string": "^7.1.3",
- "stream-json": "^1.8.0",
- "through2": "^4.0.2",
- "web-encoding": "^1.1.5",
- "xml2js": "^0.5.0 || ^0.6.2"
- },
- "engines": {
- "node": "^16 || ^18 || >=20"
- }
- },
- "node_modules/minio/node_modules/fast-xml-parser": {
- "version": "4.5.3",
- "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.3.tgz",
- "integrity": "sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/NaturalIntelligence"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "strnum": "^1.1.1"
- },
- "bin": {
- "fxparser": "src/cli/cli.js"
- }
- },
- "node_modules/minio/node_modules/ipaddr.js": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz",
- "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==",
- "license": "MIT",
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/minio/node_modules/mime-db": {
- "version": "1.52.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
- "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/minio/node_modules/mime-types": {
- "version": "2.1.35",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
- "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
- "license": "MIT",
- "dependencies": {
- "mime-db": "1.52.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/minio/node_modules/strnum": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz",
- "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/NaturalIntelligence"
- }
- ],
- "license": "MIT"
- },
- "node_modules/minipass": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
- "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
- "license": "ISC",
- "engines": {
- "node": ">=16 || 14 >=14.17"
- }
- },
- "node_modules/mkdirp": {
- "version": "0.5.6",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
- "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
- "license": "MIT",
- "dependencies": {
- "minimist": "^1.2.6"
- },
- "bin": {
- "mkdirp": "bin/cmd.js"
- }
- },
- "node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "license": "MIT"
- },
- "node_modules/multer": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/multer/-/multer-2.0.2.tgz",
- "integrity": "sha512-u7f2xaZ/UG8oLXHvtF/oWTRvT44p9ecwBBqTwgJVq0+4BW1g8OW01TyMEGWBHbyMOYVHXslaut7qEQ1meATXgw==",
- "license": "MIT",
- "dependencies": {
- "append-field": "^1.0.0",
- "busboy": "^1.6.0",
- "concat-stream": "^2.0.0",
- "mkdirp": "^0.5.6",
- "object-assign": "^4.1.1",
- "type-is": "^1.6.18",
- "xtend": "^4.0.2"
- },
- "engines": {
- "node": ">= 10.16.0"
- }
- },
- "node_modules/multer/node_modules/media-typer": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
- "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/multer/node_modules/mime-db": {
- "version": "1.52.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
- "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/multer/node_modules/mime-types": {
- "version": "2.1.35",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
- "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
- "license": "MIT",
- "dependencies": {
- "mime-db": "1.52.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/multer/node_modules/type-is": {
- "version": "1.6.18",
- "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
- "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
- "license": "MIT",
- "dependencies": {
- "media-typer": "0.3.0",
- "mime-types": "~2.1.24"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/napi-postinstall": {
- "version": "0.3.3",
- "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.3.tgz",
- "integrity": "sha512-uTp172LLXSxuSYHv/kou+f6KW3SMppU9ivthaVTXian9sOt3XM/zHYHpRZiLgQoxeWfYUnslNWQHF1+G71xcow==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "napi-postinstall": "lib/cli.js"
- },
- "engines": {
- "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/napi-postinstall"
- }
- },
- "node_modules/natural-compare": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
- "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/negotiator": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
- "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/neo-async": {
- "version": "2.6.2",
- "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
- "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/node-addon-api": {
- "version": "8.5.0",
- "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.5.0.tgz",
- "integrity": "sha512-/bRZty2mXUIFY/xU5HLvveNHlswNJej+RnxBjOMkidWfwZzgTbPG1E3K5TOxRLOR+5hX7bSofy8yf1hZevMS8A==",
- "license": "MIT",
- "engines": {
- "node": "^18 || ^20 || >= 21"
- }
- },
- "node_modules/node-gyp-build": {
- "version": "4.8.4",
- "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
- "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==",
- "license": "MIT",
- "bin": {
- "node-gyp-build": "bin.js",
- "node-gyp-build-optional": "optional.js",
- "node-gyp-build-test": "build-test.js"
- }
- },
- "node_modules/node-int64": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
- "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/node-releases": {
- "version": "2.0.19",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
- "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/nodemailer": {
- "version": "7.0.5",
- "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.5.tgz",
- "integrity": "sha512-nsrh2lO3j4GkLLXoeEksAMgAOqxOv6QumNRVQTJwKH4nuiww6iC2y7GyANs9kRAxCexg3+lTWM3PZ91iLlVjfg==",
- "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",
- "integrity": "sha512-WDjw3pJ0/0jMFmyNDp3gvY2YizjLmmOUQo6DEBY+JgdvW/yQ9mEeSw6H5ythl5Ny2ytb7f9C2nIbjSxMNzbJXw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "chokidar": "^3.5.2",
- "debug": "^4",
- "ignore-by-default": "^1.0.1",
- "minimatch": "^3.1.2",
- "pstree.remy": "^1.1.8",
- "semver": "^7.5.3",
- "simple-update-notifier": "^2.0.0",
- "supports-color": "^5.5.0",
- "touch": "^3.1.0",
- "undefsafe": "^2.0.5"
- },
- "bin": {
- "nodemon": "bin/nodemon.js"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/nodemon"
- }
- },
- "node_modules/nodemon/node_modules/brace-expansion": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
- "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/nodemon/node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/normalize-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
- "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/npm-run-path": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
- "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "path-key": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/object-assign": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
- "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/object-inspect": {
- "version": "1.13.4",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
- "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/on-finished": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
- "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
- "license": "MIT",
- "dependencies": {
- "ee-first": "1.1.1"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/once": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
- "license": "ISC",
- "dependencies": {
- "wrappy": "1"
- }
- },
- "node_modules/one-time": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz",
- "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==",
- "license": "MIT",
- "dependencies": {
- "fn.name": "1.x.x"
- }
- },
- "node_modules/onetime": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
- "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "mimic-fn": "^2.1.0"
- },
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/openapi-types": {
- "version": "12.1.3",
- "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz",
- "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==",
- "license": "MIT",
- "peer": true
- },
- "node_modules/p-limit": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
- "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "yocto-queue": "^0.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/p-locate": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
- "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "p-limit": "^2.2.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/p-locate/node_modules/p-limit": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
- "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "p-try": "^2.0.0"
- },
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/p-try": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
- "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/package-json-from-dist": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
- "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
- "license": "BlueOak-1.0.0"
- },
- "node_modules/parse-json": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
- "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.0.0",
- "error-ex": "^1.3.1",
- "json-parse-even-better-errors": "^2.3.0",
- "lines-and-columns": "^1.1.6"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/parseurl": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
- "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/path-exists": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
- "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/path-is-absolute": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/path-key": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
- "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/path-scurry": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
- "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "lru-cache": "^10.2.0",
- "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
- },
- "engines": {
- "node": ">=16 || 14 >=14.18"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/path-to-regexp": {
- "version": "8.2.0",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz",
- "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==",
- "license": "MIT",
- "engines": {
- "node": ">=16"
- }
- },
- "node_modules/pg": {
- "version": "8.16.3",
- "resolved": "https://registry.npmjs.org/pg/-/pg-8.16.3.tgz",
- "integrity": "sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw==",
- "license": "MIT",
- "dependencies": {
- "pg-connection-string": "^2.9.1",
- "pg-pool": "^3.10.1",
- "pg-protocol": "^1.10.3",
- "pg-types": "2.2.0",
- "pgpass": "1.0.5"
- },
- "engines": {
- "node": ">= 16.0.0"
- },
- "optionalDependencies": {
- "pg-cloudflare": "^1.2.7"
- },
- "peerDependencies": {
- "pg-native": ">=3.0.1"
- },
- "peerDependenciesMeta": {
- "pg-native": {
- "optional": true
- }
- }
- },
- "node_modules/pg-cloudflare": {
- "version": "1.2.7",
- "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.2.7.tgz",
- "integrity": "sha512-YgCtzMH0ptvZJslLM1ffsY4EuGaU0cx4XSdXLRFae8bPP4dS5xL1tNB3k2o/N64cHJpwU7dxKli/nZ2lUa5fLg==",
- "license": "MIT",
- "optional": true
- },
- "node_modules/pg-connection-string": {
- "version": "2.9.1",
- "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.9.1.tgz",
- "integrity": "sha512-nkc6NpDcvPVpZXxrreI/FOtX3XemeLl8E0qFr6F2Lrm/I8WOnaWNhIPK2Z7OHpw7gh5XJThi6j6ppgNoaT1w4w==",
- "license": "MIT"
- },
- "node_modules/pg-int8": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
- "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==",
- "license": "ISC",
- "engines": {
- "node": ">=4.0.0"
- }
- },
- "node_modules/pg-pool": {
- "version": "3.10.1",
- "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.10.1.tgz",
- "integrity": "sha512-Tu8jMlcX+9d8+QVzKIvM/uJtp07PKr82IUOYEphaWcoBhIYkoHpLXN3qO59nAI11ripznDsEzEv8nUxBVWajGg==",
- "license": "MIT",
- "peerDependencies": {
- "pg": ">=8.0"
- }
- },
- "node_modules/pg-protocol": {
- "version": "1.10.3",
- "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.10.3.tgz",
- "integrity": "sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ==",
- "license": "MIT"
- },
- "node_modules/pg-types": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
- "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
- "license": "MIT",
- "dependencies": {
- "pg-int8": "1.0.1",
- "postgres-array": "~2.0.0",
- "postgres-bytea": "~1.0.0",
- "postgres-date": "~1.0.4",
- "postgres-interval": "^1.1.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/pgpass": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz",
- "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==",
- "license": "MIT",
- "dependencies": {
- "split2": "^4.1.0"
- }
- },
- "node_modules/picocolors": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
- "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/picomatch": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/pirates": {
- "version": "4.0.7",
- "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz",
- "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/pkg-dir": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
- "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "find-up": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/possible-typed-array-names": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
- "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/postgres-array": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
- "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==",
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/postgres-bytea": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz",
- "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/postgres-date": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
- "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/postgres-interval": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
- "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
- "license": "MIT",
- "dependencies": {
- "xtend": "^4.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/pretty-format": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.5.tgz",
- "integrity": "sha512-D1tKtYvByrBkFLe2wHJl2bwMJIiT8rW+XA+TiataH79/FszLQMrpGEvzUVkzPau7OCO0Qnrhpe87PqtOAIB8Yw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/schemas": "30.0.5",
- "ansi-styles": "^5.2.0",
- "react-is": "^18.3.1"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/pretty-format/node_modules/ansi-styles": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
- "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/proxy-addr": {
- "version": "2.0.7",
- "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
- "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
- "license": "MIT",
- "dependencies": {
- "forwarded": "0.2.0",
- "ipaddr.js": "1.9.1"
- },
- "engines": {
- "node": ">= 0.10"
- }
- },
- "node_modules/pstree.remy": {
- "version": "1.1.8",
- "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
- "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/pure-rand": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-7.0.1.tgz",
- "integrity": "sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==",
- "dev": true,
- "funding": [
- {
- "type": "individual",
- "url": "https://github.com/sponsors/dubzzz"
- },
- {
- "type": "opencollective",
- "url": "https://opencollective.com/fast-check"
- }
- ],
- "license": "MIT"
- },
- "node_modules/qs": {
- "version": "6.14.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
- "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
- "license": "BSD-3-Clause",
- "dependencies": {
- "side-channel": "^1.1.0"
- },
- "engines": {
- "node": ">=0.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/query-string": {
- "version": "7.1.3",
- "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz",
- "integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==",
- "license": "MIT",
- "dependencies": {
- "decode-uri-component": "^0.2.2",
- "filter-obj": "^1.1.0",
- "split-on-first": "^1.0.0",
- "strict-uri-encode": "^2.0.0"
- },
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/range-parser": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
- "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/raw-body": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz",
- "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==",
- "license": "MIT",
- "dependencies": {
- "bytes": "3.1.2",
- "http-errors": "2.0.0",
- "iconv-lite": "0.6.3",
- "unpipe": "1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/react-is": {
- "version": "18.3.1",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
- "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/readable-stream": {
- "version": "3.6.2",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
- "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
- "license": "MIT",
- "dependencies": {
- "inherits": "^2.0.3",
- "string_decoder": "^1.1.1",
- "util-deprecate": "^1.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/readdirp": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
- "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "picomatch": "^2.2.1"
- },
- "engines": {
- "node": ">=8.10.0"
- }
- },
- "node_modules/redis": {
- "version": "5.8.1",
- "resolved": "https://registry.npmjs.org/redis/-/redis-5.8.1.tgz",
- "integrity": "sha512-RZjBKYX/qFF809x6vDcE5VA6L3MmiuT+BkbXbIyyyeU0lPD47V4z8qTzN+Z/kKFwpojwCItOfaItYuAjNs8pTQ==",
- "license": "MIT",
- "dependencies": {
- "@redis/bloom": "5.8.1",
- "@redis/client": "5.8.1",
- "@redis/json": "5.8.1",
- "@redis/search": "5.8.1",
- "@redis/time-series": "5.8.1"
- },
- "engines": {
- "node": ">= 18"
- }
- },
- "node_modules/reflect-metadata": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz",
- "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==",
- "license": "Apache-2.0",
- "peer": true
- },
- "node_modules/require-directory": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
- "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/resolve-cwd": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
- "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "resolve-from": "^5.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/resolve-from": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
- "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/rimraf": {
- "version": "5.0.10",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz",
- "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==",
- "dev": true,
- "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",
- "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==",
- "license": "MIT",
- "dependencies": {
- "debug": "^4.4.0",
- "depd": "^2.0.0",
- "is-promise": "^4.0.0",
- "parseurl": "^1.3.3",
- "path-to-regexp": "^8.0.0"
- },
- "engines": {
- "node": ">= 18"
- }
- },
- "node_modules/safe-buffer": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
- "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
- "funding": [
- {
- "type": "github",
- "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/safe-regex-test": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz",
- "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.2",
- "es-errors": "^1.3.0",
- "is-regex": "^1.2.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/safe-stable-stringify": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz",
- "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==",
- "license": "MIT",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/safer-buffer": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
- "license": "MIT"
- },
- "node_modules/sax": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",
- "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==",
- "license": "ISC"
- },
- "node_modules/semver": {
- "version": "7.7.2",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
- "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/send": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz",
- "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==",
- "license": "MIT",
- "dependencies": {
- "debug": "^4.3.5",
- "encodeurl": "^2.0.0",
- "escape-html": "^1.0.3",
- "etag": "^1.8.1",
- "fresh": "^2.0.0",
- "http-errors": "^2.0.0",
- "mime-types": "^3.0.1",
- "ms": "^2.1.3",
- "on-finished": "^2.4.1",
- "range-parser": "^1.2.1",
- "statuses": "^2.0.1"
- },
- "engines": {
- "node": ">= 18"
- }
- },
- "node_modules/serve-static": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz",
- "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==",
- "license": "MIT",
- "dependencies": {
- "encodeurl": "^2.0.0",
- "escape-html": "^1.0.3",
- "parseurl": "^1.3.3",
- "send": "^1.2.0"
- },
- "engines": {
- "node": ">= 18"
- }
- },
- "node_modules/set-function-length": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
- "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
- "license": "MIT",
- "dependencies": {
- "define-data-property": "^1.1.4",
- "es-errors": "^1.3.0",
- "function-bind": "^1.1.2",
- "get-intrinsic": "^1.2.4",
- "gopd": "^1.0.1",
- "has-property-descriptors": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/setprototypeof": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
- "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
- "license": "ISC"
- },
- "node_modules/sha.js": {
- "version": "2.4.12",
- "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz",
- "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==",
- "license": "(MIT AND BSD-3-Clause)",
- "dependencies": {
- "inherits": "^2.0.4",
- "safe-buffer": "^5.2.1",
- "to-buffer": "^1.2.0"
- },
- "bin": {
- "sha.js": "bin.js"
- },
- "engines": {
- "node": ">= 0.10"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/sharp": {
- "version": "0.34.4",
- "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.4.tgz",
- "integrity": "sha512-FUH39xp3SBPnxWvd5iib1X8XY7J0K0X7d93sie9CJg2PO8/7gmg89Nve6OjItK53/MlAushNNxteBYfM6DEuoA==",
- "hasInstallScript": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@img/colour": "^1.0.0",
- "detect-libc": "^2.1.0",
- "semver": "^7.7.2"
- },
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-darwin-arm64": "0.34.4",
- "@img/sharp-darwin-x64": "0.34.4",
- "@img/sharp-libvips-darwin-arm64": "1.2.3",
- "@img/sharp-libvips-darwin-x64": "1.2.3",
- "@img/sharp-libvips-linux-arm": "1.2.3",
- "@img/sharp-libvips-linux-arm64": "1.2.3",
- "@img/sharp-libvips-linux-ppc64": "1.2.3",
- "@img/sharp-libvips-linux-s390x": "1.2.3",
- "@img/sharp-libvips-linux-x64": "1.2.3",
- "@img/sharp-libvips-linuxmusl-arm64": "1.2.3",
- "@img/sharp-libvips-linuxmusl-x64": "1.2.3",
- "@img/sharp-linux-arm": "0.34.4",
- "@img/sharp-linux-arm64": "0.34.4",
- "@img/sharp-linux-ppc64": "0.34.4",
- "@img/sharp-linux-s390x": "0.34.4",
- "@img/sharp-linux-x64": "0.34.4",
- "@img/sharp-linuxmusl-arm64": "0.34.4",
- "@img/sharp-linuxmusl-x64": "0.34.4",
- "@img/sharp-wasm32": "0.34.4",
- "@img/sharp-win32-arm64": "0.34.4",
- "@img/sharp-win32-ia32": "0.34.4",
- "@img/sharp-win32-x64": "0.34.4"
- }
- },
- "node_modules/shebang-command": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
- "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
- "license": "MIT",
- "dependencies": {
- "shebang-regex": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/shebang-regex": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
- "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/side-channel": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
- "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "object-inspect": "^1.13.3",
- "side-channel-list": "^1.0.0",
- "side-channel-map": "^1.0.1",
- "side-channel-weakmap": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/side-channel-list": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
- "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "object-inspect": "^1.13.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/side-channel-map": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
- "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.2",
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.5",
- "object-inspect": "^1.13.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/side-channel-weakmap": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
- "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.2",
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.5",
- "object-inspect": "^1.13.3",
- "side-channel-map": "^1.0.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/signal-exit": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
- "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
- "license": "ISC",
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/simple-swizzle": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
- "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
- "license": "MIT",
- "dependencies": {
- "is-arrayish": "^0.3.1"
- }
- },
- "node_modules/simple-update-notifier": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz",
- "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "semver": "^7.5.3"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/slash": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
- "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/socket.io": {
- "version": "4.8.1",
- "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz",
- "integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==",
- "license": "MIT",
- "dependencies": {
- "accepts": "~1.3.4",
- "base64id": "~2.0.0",
- "cors": "~2.8.5",
- "debug": "~4.3.2",
- "engine.io": "~6.6.0",
- "socket.io-adapter": "~2.5.2",
- "socket.io-parser": "~4.2.4"
- },
- "engines": {
- "node": ">=10.2.0"
- }
- },
- "node_modules/socket.io-adapter": {
- "version": "2.5.5",
- "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz",
- "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==",
- "license": "MIT",
- "dependencies": {
- "debug": "~4.3.4",
- "ws": "~8.17.1"
- }
- },
- "node_modules/socket.io-adapter/node_modules/debug": {
- "version": "4.3.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
- "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/socket.io-client": {
- "version": "4.8.1",
- "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz",
- "integrity": "sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@socket.io/component-emitter": "~3.1.0",
- "debug": "~4.3.2",
- "engine.io-client": "~6.6.1",
- "socket.io-parser": "~4.2.4"
- },
- "engines": {
- "node": ">=10.0.0"
- }
- },
- "node_modules/socket.io-client/node_modules/debug": {
- "version": "4.3.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
- "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/socket.io-parser": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz",
- "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==",
- "license": "MIT",
- "dependencies": {
- "@socket.io/component-emitter": "~3.1.0",
- "debug": "~4.3.1"
- },
- "engines": {
- "node": ">=10.0.0"
- }
- },
- "node_modules/socket.io-parser/node_modules/debug": {
- "version": "4.3.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
- "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/socket.io/node_modules/accepts": {
- "version": "1.3.8",
- "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
- "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
- "license": "MIT",
- "dependencies": {
- "mime-types": "~2.1.34",
- "negotiator": "0.6.3"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/socket.io/node_modules/debug": {
- "version": "4.3.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
- "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/socket.io/node_modules/mime-db": {
- "version": "1.52.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
- "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/socket.io/node_modules/mime-types": {
- "version": "2.1.35",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
- "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
- "license": "MIT",
- "dependencies": {
- "mime-db": "1.52.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/socket.io/node_modules/negotiator": {
- "version": "0.6.3",
- "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
- "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true,
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/source-map-support": {
- "version": "0.5.13",
- "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
- "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "buffer-from": "^1.0.0",
- "source-map": "^0.6.0"
- }
- },
- "node_modules/split-on-first": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz",
- "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/split2": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
- "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
- "license": "ISC",
- "engines": {
- "node": ">= 10.x"
- }
- },
- "node_modules/sprintf-js": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
- "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
- "dev": true,
- "license": "BSD-3-Clause"
- },
- "node_modules/sql-highlight": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/sql-highlight/-/sql-highlight-6.1.0.tgz",
- "integrity": "sha512-ed7OK4e9ywpE7pgRMkMQmZDPKSVdm0oX5IEtZiKnFucSF0zu6c80GZBe38UqHuVhTWJ9xsKgSMjCG2bml86KvA==",
- "funding": [
- "https://github.com/scriptcoded/sql-highlight?sponsor=1",
- {
- "type": "github",
- "url": "https://github.com/sponsors/scriptcoded"
- }
- ],
- "license": "MIT",
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/stack-trace": {
- "version": "0.0.10",
- "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
- "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==",
- "license": "MIT",
- "engines": {
- "node": "*"
- }
- },
- "node_modules/stack-utils": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
- "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "escape-string-regexp": "^2.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/statuses": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
- "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/stream-chain": {
- "version": "2.2.5",
- "resolved": "https://registry.npmjs.org/stream-chain/-/stream-chain-2.2.5.tgz",
- "integrity": "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==",
- "license": "BSD-3-Clause"
- },
- "node_modules/stream-json": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/stream-json/-/stream-json-1.9.1.tgz",
- "integrity": "sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw==",
- "license": "BSD-3-Clause",
- "dependencies": {
- "stream-chain": "^2.2.5"
- }
- },
- "node_modules/streamsearch": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
- "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
- "engines": {
- "node": ">=10.0.0"
- }
- },
- "node_modules/strict-uri-encode": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
- "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==",
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/string_decoder": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
- "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
- "license": "MIT",
- "dependencies": {
- "safe-buffer": "~5.2.0"
- }
- },
- "node_modules/string-length": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
- "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "char-regex": "^1.0.2",
- "strip-ansi": "^6.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/string-length/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/string-length/node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/string-width": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
- "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
- "license": "MIT",
- "dependencies": {
- "eastasianwidth": "^0.2.0",
- "emoji-regex": "^9.2.2",
- "strip-ansi": "^7.0.1"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/string-width-cjs": {
- "name": "string-width",
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "license": "MIT",
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/string-width-cjs/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/string-width-cjs/node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "license": "MIT"
- },
- "node_modules/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==",
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/strip-ansi": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
- "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^6.0.1"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/strip-ansi?sponsor=1"
- }
- },
- "node_modules/strip-ansi-cjs": {
- "name": "strip-ansi",
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/strip-ansi-cjs/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/strip-bom": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
- "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/strip-final-newline": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
- "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/strip-json-comments": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
- "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/strnum": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.1.1.tgz",
- "integrity": "sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/NaturalIntelligence"
- }
- ],
- "license": "MIT"
- },
- "node_modules/superagent": {
- "version": "10.2.3",
- "resolved": "https://registry.npmjs.org/superagent/-/superagent-10.2.3.tgz",
- "integrity": "sha512-y/hkYGeXAj7wUMjxRbB21g/l6aAEituGXM9Rwl4o20+SX3e8YOSV6BxFXl+dL3Uk0mjSL3kCbNkwURm8/gEDig==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "component-emitter": "^1.3.1",
- "cookiejar": "^2.1.4",
- "debug": "^4.3.7",
- "fast-safe-stringify": "^2.1.1",
- "form-data": "^4.0.4",
- "formidable": "^3.5.4",
- "methods": "^1.1.2",
- "mime": "2.6.0",
- "qs": "^6.11.2"
- },
- "engines": {
- "node": ">=14.18.0"
- }
- },
- "node_modules/supertest": {
- "version": "7.1.4",
- "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.1.4.tgz",
- "integrity": "sha512-tjLPs7dVyqgItVFirHYqe2T+MfWc2VOBQ8QFKKbWTA3PU7liZR8zoSpAi/C1k1ilm9RsXIKYf197oap9wXGVYg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "methods": "^1.1.2",
- "superagent": "^10.2.3"
- },
- "engines": {
- "node": ">=14.18.0"
- }
- },
- "node_modules/supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "has-flag": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/swagger-jsdoc": {
- "version": "6.2.8",
- "resolved": "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-6.2.8.tgz",
- "integrity": "sha512-VPvil1+JRpmJ55CgAtn8DIcpBs0bL5L3q5bVQvF4tAW/k/9JYSj7dCpaYCAv5rufe0vcCbBRQXGvzpkWjvLklQ==",
- "license": "MIT",
- "dependencies": {
- "commander": "6.2.0",
- "doctrine": "3.0.0",
- "glob": "7.1.6",
- "lodash.mergewith": "^4.6.2",
- "swagger-parser": "^10.0.3",
- "yaml": "2.0.0-1"
- },
- "bin": {
- "swagger-jsdoc": "bin/swagger-jsdoc.js"
- },
- "engines": {
- "node": ">=12.0.0"
- }
- },
- "node_modules/swagger-jsdoc/node_modules/brace-expansion": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
- "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/swagger-jsdoc/node_modules/glob": {
- "version": "7.1.6",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
- "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
- "deprecated": "Glob versions prior to v9 are no longer supported",
- "license": "ISC",
- "dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.0.4",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- },
- "engines": {
- "node": "*"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/swagger-jsdoc/node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/swagger-parser": {
- "version": "10.0.3",
- "resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-10.0.3.tgz",
- "integrity": "sha512-nF7oMeL4KypldrQhac8RyHerJeGPD1p2xDh900GPvc+Nk7nWP6jX2FcC7WmkinMoAmoO774+AFXcWsW8gMWEIg==",
- "license": "MIT",
- "dependencies": {
- "@apidevtools/swagger-parser": "10.0.3"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/swagger-ui-dist": {
- "version": "5.27.1",
- "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.27.1.tgz",
- "integrity": "sha512-oGtpYO3lnoaqyGtlJalvryl7TwzgRuxpOVWqEHx8af0YXI+Kt+4jMpLdgMtMcmWmuQ0QTCHLKExwrBFMSxvAUA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@scarf/scarf": "=1.4.0"
- }
- },
- "node_modules/swagger-ui-express": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.1.tgz",
- "integrity": "sha512-SrNU3RiBGTLLmFU8GIJdOdanJTl4TOmT27tt3bWWHppqYmAZ6IDuEuBvMU6nZq0zLEe6b/1rACXCgLZqO6ZfrA==",
- "license": "MIT",
- "dependencies": {
- "swagger-ui-dist": ">=5.0.0"
- },
- "engines": {
- "node": ">= v0.10.32"
- },
- "peerDependencies": {
- "express": ">=4.0.0 || >=5.0.0-beta"
- }
- },
- "node_modules/synckit": {
- "version": "0.11.11",
- "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz",
- "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@pkgr/core": "^0.2.9"
- },
- "engines": {
- "node": "^14.18.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/synckit"
- }
- },
- "node_modules/test-exclude": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
- "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "@istanbuljs/schema": "^0.1.2",
- "glob": "^7.1.4",
- "minimatch": "^3.0.4"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/test-exclude/node_modules/brace-expansion": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
- "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/test-exclude/node_modules/glob": {
- "version": "7.2.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
- "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
- "deprecated": "Glob versions prior to v9 are no longer supported",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.1.1",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- },
- "engines": {
- "node": "*"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/test-exclude/node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/text-hex": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz",
- "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==",
- "license": "MIT"
- },
- "node_modules/through2": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz",
- "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==",
- "license": "MIT",
- "dependencies": {
- "readable-stream": "3"
- }
- },
- "node_modules/tmpl": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
- "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
- "dev": true,
- "license": "BSD-3-Clause"
- },
- "node_modules/to-buffer": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.1.tgz",
- "integrity": "sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==",
- "license": "MIT",
- "dependencies": {
- "isarray": "^2.0.5",
- "safe-buffer": "^5.2.1",
- "typed-array-buffer": "^1.0.3"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/to-regex-range": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
- "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-number": "^7.0.0"
- },
- "engines": {
- "node": ">=8.0"
- }
- },
- "node_modules/toidentifier": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
- "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
- "license": "MIT",
- "engines": {
- "node": ">=0.6"
- }
- },
- "node_modules/touch": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz",
- "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "nodetouch": "bin/nodetouch.js"
- }
- },
- "node_modules/triple-beam": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz",
- "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==",
- "license": "MIT",
- "engines": {
- "node": ">= 14.0.0"
- }
- },
- "node_modules/ts-jest": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.1.tgz",
- "integrity": "sha512-SaeUtjfpg9Uqu8IbeDKtdaS0g8lS6FT6OzM3ezrDfErPJPHNDo/Ey+VFGP1bQIDfagYDLyRpd7O15XpG1Es2Uw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "bs-logger": "^0.2.6",
- "fast-json-stable-stringify": "^2.1.0",
- "handlebars": "^4.7.8",
- "json5": "^2.2.3",
- "lodash.memoize": "^4.1.2",
- "make-error": "^1.3.6",
- "semver": "^7.7.2",
- "type-fest": "^4.41.0",
- "yargs-parser": "^21.1.1"
- },
- "bin": {
- "ts-jest": "cli.js"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0"
- },
- "peerDependencies": {
- "@babel/core": ">=7.0.0-beta.0 <8",
- "@jest/transform": "^29.0.0 || ^30.0.0",
- "@jest/types": "^29.0.0 || ^30.0.0",
- "babel-jest": "^29.0.0 || ^30.0.0",
- "jest": "^29.0.0 || ^30.0.0",
- "jest-util": "^29.0.0 || ^30.0.0",
- "typescript": ">=4.3 <6"
- },
- "peerDependenciesMeta": {
- "@babel/core": {
- "optional": true
- },
- "@jest/transform": {
- "optional": true
- },
- "@jest/types": {
- "optional": true
- },
- "babel-jest": {
- "optional": true
- },
- "esbuild": {
- "optional": true
- },
- "jest-util": {
- "optional": true
- }
- }
- },
- "node_modules/ts-jest/node_modules/type-fest": {
- "version": "4.41.0",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz",
- "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==",
- "dev": true,
- "license": "(MIT OR CC0-1.0)",
- "engines": {
- "node": ">=16"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/ts-node": {
- "version": "10.9.2",
- "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
- "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
- "devOptional": true,
- "license": "MIT",
- "dependencies": {
- "@cspotcode/source-map-support": "^0.8.0",
- "@tsconfig/node10": "^1.0.7",
- "@tsconfig/node12": "^1.0.7",
- "@tsconfig/node14": "^1.0.0",
- "@tsconfig/node16": "^1.0.2",
- "acorn": "^8.4.1",
- "acorn-walk": "^8.1.1",
- "arg": "^4.1.0",
- "create-require": "^1.1.0",
- "diff": "^4.0.1",
- "make-error": "^1.1.1",
- "v8-compile-cache-lib": "^3.0.1",
- "yn": "3.1.1"
- },
- "bin": {
- "ts-node": "dist/bin.js",
- "ts-node-cwd": "dist/bin-cwd.js",
- "ts-node-esm": "dist/bin-esm.js",
- "ts-node-script": "dist/bin-script.js",
- "ts-node-transpile-only": "dist/bin-transpile.js",
- "ts-script": "dist/bin-script-deprecated.js"
- },
- "peerDependencies": {
- "@swc/core": ">=1.2.50",
- "@swc/wasm": ">=1.2.50",
- "@types/node": "*",
- "typescript": ">=2.7"
- },
- "peerDependenciesMeta": {
- "@swc/core": {
- "optional": true
- },
- "@swc/wasm": {
- "optional": true
- }
- }
- },
- "node_modules/tsconfig-paths": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz",
- "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==",
- "license": "MIT",
- "dependencies": {
- "json5": "^2.2.2",
- "minimist": "^1.2.6",
- "strip-bom": "^3.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/tslib": {
- "version": "2.8.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
- "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
- "license": "0BSD"
- },
- "node_modules/type-detect": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
- "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/type-fest": {
- "version": "0.21.3",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
- "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
- "dev": true,
- "license": "(MIT OR CC0-1.0)",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/type-is": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
- "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==",
- "license": "MIT",
- "dependencies": {
- "content-type": "^1.0.5",
- "media-typer": "^1.1.0",
- "mime-types": "^3.0.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/typed-array-buffer": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
- "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3",
- "es-errors": "^1.3.0",
- "is-typed-array": "^1.1.14"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/typedarray": {
- "version": "0.0.6",
- "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
- "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
- "license": "MIT"
- },
- "node_modules/typeorm": {
- "version": "0.3.26",
- "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.26.tgz",
- "integrity": "sha512-o2RrBNn3lczx1qv4j+JliVMmtkPSqEGpG0UuZkt9tCfWkoXKu8MZnjvp2GjWPll1SehwemQw6xrbVRhmOglj8Q==",
- "license": "MIT",
- "dependencies": {
- "@sqltools/formatter": "^1.2.5",
- "ansis": "^3.17.0",
- "app-root-path": "^3.1.0",
- "buffer": "^6.0.3",
- "dayjs": "^1.11.13",
- "debug": "^4.4.0",
- "dedent": "^1.6.0",
- "dotenv": "^16.4.7",
- "glob": "^10.4.5",
- "sha.js": "^2.4.11",
- "sql-highlight": "^6.0.0",
- "tslib": "^2.8.1",
- "uuid": "^11.1.0",
- "yargs": "^17.7.2"
- },
- "bin": {
- "typeorm": "cli.js",
- "typeorm-ts-node-commonjs": "cli-ts-node-commonjs.js",
- "typeorm-ts-node-esm": "cli-ts-node-esm.js"
- },
- "engines": {
- "node": ">=16.13.0"
- },
- "funding": {
- "url": "https://opencollective.com/typeorm"
- },
- "peerDependencies": {
- "@google-cloud/spanner": "^5.18.0 || ^6.0.0 || ^7.0.0",
- "@sap/hana-client": "^2.14.22",
- "better-sqlite3": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0",
- "ioredis": "^5.0.4",
- "mongodb": "^5.8.0 || ^6.0.0",
- "mssql": "^9.1.1 || ^10.0.1 || ^11.0.1",
- "mysql2": "^2.2.5 || ^3.0.1",
- "oracledb": "^6.3.0",
- "pg": "^8.5.1",
- "pg-native": "^3.0.0",
- "pg-query-stream": "^4.0.0",
- "redis": "^3.1.1 || ^4.0.0 || ^5.0.14",
- "reflect-metadata": "^0.1.14 || ^0.2.0",
- "sql.js": "^1.4.0",
- "sqlite3": "^5.0.3",
- "ts-node": "^10.7.0",
- "typeorm-aurora-data-api-driver": "^2.0.0 || ^3.0.0"
- },
- "peerDependenciesMeta": {
- "@google-cloud/spanner": {
- "optional": true
- },
- "@sap/hana-client": {
- "optional": true
- },
- "better-sqlite3": {
- "optional": true
- },
- "ioredis": {
- "optional": true
- },
- "mongodb": {
- "optional": true
- },
- "mssql": {
- "optional": true
- },
- "mysql2": {
- "optional": true
- },
- "oracledb": {
- "optional": true
- },
- "pg": {
- "optional": true
- },
- "pg-native": {
- "optional": true
- },
- "pg-query-stream": {
- "optional": true
- },
- "redis": {
- "optional": true
- },
- "sql.js": {
- "optional": true
- },
- "sqlite3": {
- "optional": true
- },
- "ts-node": {
- "optional": true
- },
- "typeorm-aurora-data-api-driver": {
- "optional": true
- }
- }
- },
- "node_modules/typescript": {
- "version": "5.9.2",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz",
- "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
- "devOptional": true,
- "license": "Apache-2.0",
- "bin": {
- "tsc": "bin/tsc",
- "tsserver": "bin/tsserver"
- },
- "engines": {
- "node": ">=14.17"
- }
- },
- "node_modules/uglify-js": {
- "version": "3.19.3",
- "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz",
- "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==",
- "dev": true,
- "license": "BSD-2-Clause",
- "optional": true,
- "bin": {
- "uglifyjs": "bin/uglifyjs"
- },
- "engines": {
- "node": ">=0.8.0"
- }
- },
- "node_modules/undefsafe": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
- "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/undici-types": {
- "version": "7.10.0",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz",
- "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==",
- "license": "MIT"
- },
- "node_modules/unpipe": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
- "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/unrs-resolver": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz",
- "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==",
- "dev": true,
- "hasInstallScript": true,
- "license": "MIT",
- "dependencies": {
- "napi-postinstall": "^0.3.0"
- },
- "funding": {
- "url": "https://opencollective.com/unrs-resolver"
- },
- "optionalDependencies": {
- "@unrs/resolver-binding-android-arm-eabi": "1.11.1",
- "@unrs/resolver-binding-android-arm64": "1.11.1",
- "@unrs/resolver-binding-darwin-arm64": "1.11.1",
- "@unrs/resolver-binding-darwin-x64": "1.11.1",
- "@unrs/resolver-binding-freebsd-x64": "1.11.1",
- "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1",
- "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1",
- "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1",
- "@unrs/resolver-binding-linux-arm64-musl": "1.11.1",
- "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1",
- "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1",
- "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1",
- "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1",
- "@unrs/resolver-binding-linux-x64-gnu": "1.11.1",
- "@unrs/resolver-binding-linux-x64-musl": "1.11.1",
- "@unrs/resolver-binding-wasm32-wasi": "1.11.1",
- "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1",
- "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1",
- "@unrs/resolver-binding-win32-x64-msvc": "1.11.1"
- }
- },
- "node_modules/update-browserslist-db": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
- "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/browserslist"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "escalade": "^3.2.0",
- "picocolors": "^1.1.1"
- },
- "bin": {
- "update-browserslist-db": "cli.js"
- },
- "peerDependencies": {
- "browserslist": ">= 4.21.0"
- }
- },
- "node_modules/util": {
- "version": "0.12.5",
- "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz",
- "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==",
- "license": "MIT",
- "dependencies": {
- "inherits": "^2.0.3",
- "is-arguments": "^1.0.4",
- "is-generator-function": "^1.0.7",
- "is-typed-array": "^1.1.3",
- "which-typed-array": "^1.1.2"
- }
- },
- "node_modules/util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
- "license": "MIT"
- },
- "node_modules/uuid": {
- "version": "11.1.0",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz",
- "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==",
- "funding": [
- "https://github.com/sponsors/broofa",
- "https://github.com/sponsors/ctavan"
- ],
- "license": "MIT",
- "bin": {
- "uuid": "dist/esm/bin/uuid"
- }
- },
- "node_modules/v8-compile-cache-lib": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
- "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
- "devOptional": true,
- "license": "MIT"
- },
- "node_modules/v8-to-istanbul": {
- "version": "9.3.0",
- "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz",
- "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "@jridgewell/trace-mapping": "^0.3.12",
- "@types/istanbul-lib-coverage": "^2.0.1",
- "convert-source-map": "^2.0.0"
- },
- "engines": {
- "node": ">=10.12.0"
- }
- },
- "node_modules/v8-to-istanbul/node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.30",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz",
- "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
- }
- },
- "node_modules/validator": {
- "version": "13.15.15",
- "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.15.tgz",
- "integrity": "sha512-BgWVbCI72aIQy937xbawcs+hrVaN/CZ2UwutgaJ36hGqRrLNM+f5LUT/YPRbo8IV/ASeFzXszezV+y2+rq3l8A==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.10"
- }
- },
- "node_modules/vary": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
- "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/walker": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
- "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "makeerror": "1.0.12"
- }
- },
- "node_modules/web-encoding": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/web-encoding/-/web-encoding-1.1.5.tgz",
- "integrity": "sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==",
- "license": "MIT",
- "dependencies": {
- "util": "^0.12.3"
- },
- "optionalDependencies": {
- "@zxing/text-encoding": "0.9.0"
- }
- },
- "node_modules/which": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
- "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "license": "ISC",
- "dependencies": {
- "isexe": "^2.0.0"
- },
- "bin": {
- "node-which": "bin/node-which"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/which-typed-array": {
- "version": "1.1.19",
- "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz",
- "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==",
- "license": "MIT",
- "dependencies": {
- "available-typed-arrays": "^1.0.7",
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.4",
- "for-each": "^0.3.5",
- "get-proto": "^1.0.1",
- "gopd": "^1.2.0",
- "has-tostringtag": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/winston": {
- "version": "3.17.0",
- "resolved": "https://registry.npmjs.org/winston/-/winston-3.17.0.tgz",
- "integrity": "sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw==",
- "license": "MIT",
- "dependencies": {
- "@colors/colors": "^1.6.0",
- "@dabh/diagnostics": "^2.0.2",
- "async": "^3.2.3",
- "is-stream": "^2.0.0",
- "logform": "^2.7.0",
- "one-time": "^1.0.0",
- "readable-stream": "^3.4.0",
- "safe-stable-stringify": "^2.3.1",
- "stack-trace": "0.0.x",
- "triple-beam": "^1.3.0",
- "winston-transport": "^4.9.0"
- },
- "engines": {
- "node": ">= 12.0.0"
- }
- },
- "node_modules/winston-transport": {
- "version": "4.9.0",
- "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.9.0.tgz",
- "integrity": "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==",
- "license": "MIT",
- "dependencies": {
- "logform": "^2.7.0",
- "readable-stream": "^3.6.2",
- "triple-beam": "^1.3.0"
- },
- "engines": {
- "node": ">= 12.0.0"
- }
- },
- "node_modules/wordwrap": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
- "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/wrap-ansi": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
- "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^6.1.0",
- "string-width": "^5.0.1",
- "strip-ansi": "^7.0.1"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
- }
- },
- "node_modules/wrap-ansi-cjs": {
- "name": "wrap-ansi",
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
- "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
- }
- },
- "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "license": "MIT",
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "license": "MIT"
- },
- "node_modules/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==",
- "license": "MIT",
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/wrap-ansi-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==",
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
- "license": "ISC"
- },
- "node_modules/write-file-atomic": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz",
- "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "imurmurhash": "^0.1.4",
- "signal-exit": "^4.0.1"
- },
- "engines": {
- "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
- }
- },
- "node_modules/ws": {
- "version": "8.17.1",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
- "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
- "license": "MIT",
- "engines": {
- "node": ">=10.0.0"
- },
- "peerDependencies": {
- "bufferutil": "^4.0.1",
- "utf-8-validate": ">=5.0.2"
- },
- "peerDependenciesMeta": {
- "bufferutil": {
- "optional": true
- },
- "utf-8-validate": {
- "optional": true
- }
- }
- },
- "node_modules/xml2js": {
- "version": "0.6.2",
- "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz",
- "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==",
- "license": "MIT",
- "dependencies": {
- "sax": ">=0.6.0",
- "xmlbuilder": "~11.0.0"
- },
- "engines": {
- "node": ">=4.0.0"
- }
- },
- "node_modules/xmlbuilder": {
- "version": "11.0.1",
- "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
- "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
- "license": "MIT",
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/xmlhttprequest-ssl": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz",
- "integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==",
- "dev": true,
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/xtend": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
- "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
- "license": "MIT",
- "engines": {
- "node": ">=0.4"
- }
- },
- "node_modules/y18n": {
- "version": "5.0.8",
- "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
- "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
- "license": "ISC",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/yallist": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
- "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/yaml": {
- "version": "2.0.0-1",
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.0.0-1.tgz",
- "integrity": "sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ==",
- "license": "ISC",
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/yargs": {
- "version": "17.7.2",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
- "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
- "license": "MIT",
- "dependencies": {
- "cliui": "^8.0.1",
- "escalade": "^3.1.1",
- "get-caller-file": "^2.0.5",
- "require-directory": "^2.1.1",
- "string-width": "^4.2.3",
- "y18n": "^5.0.5",
- "yargs-parser": "^21.1.1"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/yargs-parser": {
- "version": "21.1.1",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
- "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/yargs/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/yargs/node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "license": "MIT"
- },
- "node_modules/yargs/node_modules/string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "license": "MIT",
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/yargs/node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/yn": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
- "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
- "devOptional": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/yocto-queue": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
- "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/z-schema": {
- "version": "5.0.5",
- "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz",
- "integrity": "sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==",
- "license": "MIT",
- "dependencies": {
- "lodash.get": "^4.4.2",
- "lodash.isequal": "^4.5.0",
- "validator": "^13.7.0"
- },
- "bin": {
- "z-schema": "bin/z-schema"
- },
- "engines": {
- "node": ">=8.0.0"
- },
- "optionalDependencies": {
- "commander": "^9.4.1"
- }
- },
- "node_modules/z-schema/node_modules/commander": {
- "version": "9.5.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
- "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": "^12.20.0 || >=14"
- }
- }
- }
-}
diff --git a/SerpentRace_Backend/package.json b/SerpentRace_Backend/package.json
deleted file mode 100644
index 0999f1bd..00000000
--- a/SerpentRace_Backend/package.json
+++ /dev/null
@@ -1,89 +0,0 @@
-{
- "name": "serpentrace_backend",
- "version": "1.0.0",
- "description": "",
- "license": "ISC",
- "author": "",
- "type": "commonjs",
- "main": "index.js",
- "scripts": {
- "test": "jest",
- "test:watch": "jest --watch",
- "test:coverage": "jest --coverage",
- "test:redis": "jest --testNamePattern=\"RedisService\"",
- "start": "node ./dist/Api/index.js",
- "dev": "nodemon --watch src --ext ts,json --exec ts-node ./src/Api/index.ts",
- "build": "npm run build:clean && npm run build:compile && npm run build:copy-assets",
- "build:clean": "rimraf dist",
- "build:compile": "tsc",
- "build:copy-assets": "node scripts/copy-assets.js",
- "build:production": "npm run build:clean && npm run lint && npm run test && npm run migration:run && npm run build:compile && npm run build:copy-assets",
- "build:docker": "npm run build:clean && npm run build:compile && npm run build:copy-assets",
- "build:advanced": "ts-node scripts/build.ts",
- "build:advanced:prod": "ts-node scripts/build.ts --production --migrations --test",
- "build:advanced:ci": "ts-node scripts/build.ts --production --migrations --test --skip-lint",
- "deploy": "node -e \"console.log('Use deploy.bat on Windows or deploy.sh on Linux/Mac')\"",
- "deploy:prod": "npm run build:production && echo 'Build completed - ready for deployment'",
- "build:help": "node scripts/build-help.js",
- "build:status": "node scripts/build-help.js --status",
- "build:quick": "node scripts/build-help.js --quick",
- "prebuild": "npm run lint",
- "postbuild": "echo 'Build completed successfully!'",
- "lint": "echo 'Linting...' && echo 'No linter configured - add ESLint if needed'",
- "migration:create": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli migration:create",
- "migration:generate": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli -d ./src/Infrastructure/ormconfig.ts migration:generate",
- "migration:run": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli -d ./src/Infrastructure/ormconfig.ts migration:run",
- "migration:revert": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli -d ./src/Infrastructure/ormconfig.ts migration:revert",
- "migration:show": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli -d ./src/Infrastructure/ormconfig.ts migration:show",
- "migration:full": "ts-node scripts/generate-migration.ts",
- "typecheck": "tsc --noEmit",
- "watch": "tsc --watch"
- },
- "dependencies": {
- "bcrypt": "^6.0.0",
- "cookie-parser": "^1.4.7",
- "express": "^5.1.0",
- "helmet": "^8.1.0",
- "jsonwebtoken": "^9.0.2",
- "minio": "^8.0.5",
- "multer": "^2.0.2",
- "nodemailer": "^7.0.5",
- "pg": "^8.16.3",
- "redis": "^5.8.1",
- "sharp": "^0.34.4",
- "socket.io": "^4.8.1",
- "swagger-jsdoc": "^6.2.8",
- "swagger-ui-express": "^5.0.1",
- "tsconfig-paths": "^4.2.0",
- "typeorm": "^0.3.26",
- "uuid": "^11.1.0",
- "winston": "^3.17.0"
- },
- "devDependencies": {
- "@jest/globals": "^30.0.5",
- "@types/bcrypt": "^6.0.0",
- "@types/cookie-parser": "^1.4.9",
- "@types/express": "^5.0.3",
- "@types/jest": "^30.0.0",
- "@types/jsonwebtoken": "^9.0.10",
- "@types/multer": "^2.0.0",
- "@types/node": "^24.3.3",
- "@types/nodemailer": "^7.0.1",
- "@types/pg": "^8.15.5",
- "@types/redis": "^4.0.10",
- "@types/socket.io": "^3.0.1",
- "@types/socket.io-client": "^1.4.36",
- "@types/supertest": "^6.0.3",
- "@types/swagger-jsdoc": "^6.0.4",
- "@types/swagger-ui-express": "^4.1.8",
- "@types/uuid": "^10.0.0",
- "jest": "^30.0.5",
- "nodemon": "^3.1.10",
- "rimraf": "^5.0.10",
- "socket.io-client": "^4.8.1",
- "supertest": "^7.1.4",
- "ts-jest": "^29.4.1",
- "ts-node": "^10.9.2",
- "typescript": "^5.9.2"
- }
-}
diff --git a/SerpentRace_Backend/scripts/build-help.js b/SerpentRace_Backend/scripts/build-help.js
deleted file mode 100644
index 183e9dff..00000000
--- a/SerpentRace_Backend/scripts/build-help.js
+++ /dev/null
@@ -1,115 +0,0 @@
-#!/usr/bin/env node
-
-const { execSync } = require('child_process');
-const fs = require('fs');
-const path = require('path');
-
-/**
- * Build System Helper - Shows available build commands and their descriptions
- */
-
-const commands = {
- 'Development Commands': {
- 'npm run dev': 'Start development server with hot reload',
- 'npm run watch': 'Watch mode TypeScript compilation',
- 'npm run typecheck': 'Type checking without code generation'
- },
- 'Build Commands': {
- 'npm run build': 'Standard build: clean â compile â copy assets',
- 'npm run build:clean': 'Clean the dist directory',
- 'npm run build:compile': 'Compile TypeScript to JavaScript',
- 'npm run build:copy-assets': 'Copy non-TS files to dist directory',
- 'npm run build:docker': 'Build for Docker (no tests/migrations)'
- },
- 'Production Build Commands': {
- 'npm run build:production': 'Full production build with linting, tests, and migrations',
- 'npm run build:advanced': 'Advanced build script with custom options',
- 'npm run build:advanced:prod': 'Advanced production build with all validations',
- 'npm run build:advanced:ci': 'CI/CD friendly build (skips linting)',
- 'npm run deploy:prod': 'Build for production deployment'
- },
- 'Database Commands': {
- 'npm run migration:run': 'Run pending database migrations',
- 'npm run migration:show': 'Show migration status',
- 'npm run migration:generate ': 'Generate new migration',
- 'npm run migration:create ': 'Create empty migration',
- 'npm run migration:revert': 'Revert last migration',
- 'npm run migration:full ': 'Create, generate, and run migration'
- },
- 'Testing Commands': {
- 'npm test': 'Run all tests',
- 'npm run test:watch': 'Run tests in watch mode',
- 'npm run test:coverage': 'Run tests with coverage report',
- 'npm run test:redis': 'Run Redis-specific tests'
- },
- 'Deployment Scripts': {
- 'scripts/deploy.sh': 'Full Linux/Mac deployment script',
- 'scripts/deploy.bat': 'Full Windows deployment script'
- }
-};
-
-function showCommands() {
- console.log('đ§ SerpentRace Backend Build System\n');
-
- Object.entries(commands).forEach(([category, categoryCommands]) => {
- console.log(`\x1b[36m${category}\x1b[0m`);
- console.log('=' .repeat(category.length));
-
- Object.entries(categoryCommands).forEach(([command, description]) => {
- console.log(` \x1b[32m${command.padEnd(35)}\x1b[0m ${description}`);
- });
-
- console.log('');
- });
-
- console.log('\x1b[33mQuick Start:\x1b[0m');
- console.log(' npm run build # Basic build');
- console.log(' npm run build:production # Production build');
- console.log(' npm run dev # Development server\n');
-
- console.log('\x1b[33mDocumentation:\x1b[0m');
- console.log(' See BUILD.md for detailed documentation');
-}
-
-function checkBuildStatus() {
- const distPath = path.join(__dirname, '..', 'dist');
-
- if (fs.existsSync(distPath)) {
- const stats = fs.statSync(distPath);
- console.log(`\x1b[32mâ
Last build:\x1b[0m ${stats.mtime.toLocaleString()}`);
-
- const indexPath = path.join(distPath, 'Api', 'index.js');
- if (fs.existsSync(indexPath)) {
- console.log('\x1b[32mâ
Main entry point built successfully\x1b[0m');
- } else {
- console.log('\x1b[31mâ Main entry point missing\x1b[0m');
- }
- } else {
- console.log('\x1b[33mâ ïž No build found - run "npm run build" first\x1b[0m');
- }
-}
-
-// Handle command line arguments
-const args = process.argv.slice(2);
-
-if (args.includes('--help') || args.includes('-h')) {
- showCommands();
-} else if (args.includes('--status') || args.includes('-s')) {
- checkBuildStatus();
-} else if (args.includes('--quick') || args.includes('-q')) {
- console.log('đ Quick build starting...');
- try {
- execSync('npm run build', { stdio: 'inherit' });
- } catch (error) {
- console.error('â Quick build failed');
- process.exit(1);
- }
-} else {
- showCommands();
- checkBuildStatus();
-
- console.log('\n\x1b[33mOptions:\x1b[0m');
- console.log(' --help, -h Show this help');
- console.log(' --status, -s Show build status only');
- console.log(' --quick, -q Run quick build');
-}
diff --git a/SerpentRace_Backend/scripts/build.ts b/SerpentRace_Backend/scripts/build.ts
deleted file mode 100644
index 81185407..00000000
--- a/SerpentRace_Backend/scripts/build.ts
+++ /dev/null
@@ -1,187 +0,0 @@
-import { execSync } from 'child_process';
-import { existsSync, rmSync } from 'fs';
-import { join } from 'path';
-
-/**
- * Comprehensive Build Script for SerpentRace Backend
- * Handles TypeScript compilation, migrations, asset copying, and validation
- */
-
-interface BuildOptions {
- runMigrations?: boolean;
- runTests?: boolean;
- skipLinting?: boolean;
- production?: boolean;
-}
-
-class BuildManager {
- private distDir = join(__dirname, '..', 'dist');
-
- constructor(private options: BuildOptions = {}) {}
-
- private log(message: string, level: 'info' | 'error' | 'warn' = 'info') {
- const timestamp = new Date().toISOString();
- const prefix = {
- info: 'đ§',
- error: 'â',
- warn: 'â ïž'
- }[level];
- console.log(`${prefix} [${timestamp}] ${message}`);
- }
-
- private execute(command: string, description: string) {
- this.log(`${description}...`);
- try {
- execSync(command, {
- stdio: 'inherit',
- cwd: join(__dirname, '..')
- });
- this.log(`â
${description} completed successfully`);
- } catch (error) {
- this.log(`â ${description} failed`, 'error');
- throw error;
- }
- }
-
- async clean() {
- this.log('Cleaning previous build...');
- if (existsSync(this.distDir)) {
- rmSync(this.distDir, { recursive: true, force: true });
- this.log('â
Previous build cleaned');
- } else {
- this.log('No previous build found');
- }
- }
-
- async typecheck() {
- this.execute('npx tsc --noEmit', 'Type checking');
- }
-
- async lint() {
- if (this.options.skipLinting) {
- this.log('Skipping linting...', 'warn');
- return;
- }
-
- // For now, just check if TypeScript compiles without errors
- this.log('Linting (basic type checking)...');
- await this.typecheck();
- }
-
- async runTests() {
- if (!this.options.runTests) {
- this.log('Skipping tests...', 'warn');
- return;
- }
-
- this.execute('npm test', 'Running tests');
- }
-
- async runMigrations() {
- if (!this.options.runMigrations) {
- this.log('Skipping database migrations...', 'warn');
- return;
- }
-
- try {
- this.log('Checking migration status...');
- execSync('npm run migration:show', {
- stdio: 'pipe',
- cwd: join(__dirname, '..')
- });
-
- this.execute('npm run migration:run', 'Running database migrations');
- } catch (error) {
- this.log('Migration check/run failed - this might be expected in CI/CD environments', 'warn');
- if (this.options.production) {
- throw error; // In production builds, migrations should work
- }
- }
- }
-
- async compile() {
- this.execute('npx tsc', 'Compiling TypeScript');
- }
-
- async copyAssets() {
- this.execute('node scripts/copy-assets.js', 'Copying assets');
- }
-
- async validateBuild() {
- this.log('Validating build output...');
-
- const expectedFiles = [
- 'dist/Api/index.js',
- 'dist/Api/index.d.ts'
- ];
-
- const missingFiles = expectedFiles.filter(file =>
- !existsSync(join(__dirname, '..', file))
- );
-
- if (missingFiles.length > 0) {
- this.log(`Missing expected build files: ${missingFiles.join(', ')}`, 'error');
- throw new Error('Build validation failed');
- }
-
- this.log('â
Build validation completed');
- }
-
- async build() {
- const startTime = Date.now();
-
- try {
- this.log('đ Starting SerpentRace Backend build process...');
-
- // Step 1: Clean previous build
- await this.clean();
-
- // Step 2: Lint code (if not skipped)
- await this.lint();
-
- // Step 3: Run tests (if enabled)
- await this.runTests();
-
- // Step 4: Run migrations (if enabled)
- await this.runMigrations();
-
- // Step 5: Compile TypeScript
- await this.compile();
-
- // Step 6: Copy assets
- await this.copyAssets();
-
- // Step 7: Validate build
- await this.validateBuild();
-
- const duration = ((Date.now() - startTime) / 1000).toFixed(2);
- this.log(`đ Build completed successfully in ${duration}s`);
-
- } catch (error) {
- const duration = ((Date.now() - startTime) / 1000).toFixed(2);
- this.log(`đ„ Build failed after ${duration}s`, 'error');
-
- if (error instanceof Error) {
- this.log(`Error: ${error.message}`, 'error');
- }
-
- process.exit(1);
- }
- }
-}
-
-// Parse command line arguments
-const args = process.argv.slice(2);
-const options: BuildOptions = {
- runMigrations: args.includes('--migrations'),
- runTests: args.includes('--test'),
- skipLinting: args.includes('--skip-lint'),
- production: args.includes('--production')
-};
-
-// Create and run build
-const buildManager = new BuildManager(options);
-buildManager.build().catch(error => {
- console.error('Unhandled build error:', error);
- process.exit(1);
-});
diff --git a/SerpentRace_Backend/scripts/copy-assets.js b/SerpentRace_Backend/scripts/copy-assets.js
deleted file mode 100644
index 1f9c26e3..00000000
--- a/SerpentRace_Backend/scripts/copy-assets.js
+++ /dev/null
@@ -1,62 +0,0 @@
-const fs = require('fs');
-const path = require('path');
-
-/**
- * Copy Assets Script for SerpentRace Backend
- * Copies non-TypeScript files to the dist directory
- */
-
-const srcDir = path.join(__dirname, '..', 'src');
-const distDir = path.join(__dirname, '..', 'dist');
-
-// File extensions to copy
-const assetExtensions = ['.json', '.html', '.css', '.png', '.jpg', '.jpeg', '.gif', '.svg', '.ico', '.woff', '.woff2', '.ttf', '.eot'];
-
-// Directories to exclude from copying
-const excludeDirs = ['node_modules', '.git', 'tests', '__tests__'];
-
-function copyAssets(srcPath, distPath) {
- if (!fs.existsSync(srcPath)) {
- console.log(`Source directory ${srcPath} does not exist`);
- return;
- }
-
- if (!fs.existsSync(distPath)) {
- fs.mkdirSync(distPath, { recursive: true });
- }
-
- const items = fs.readdirSync(srcPath);
-
- items.forEach(item => {
- const srcItemPath = path.join(srcPath, item);
- const distItemPath = path.join(distPath, item);
- const stat = fs.statSync(srcItemPath);
-
- if (stat.isDirectory()) {
- // Skip excluded directories
- if (excludeDirs.includes(item)) {
- return;
- }
-
- // Recursively copy subdirectories
- copyAssets(srcItemPath, distItemPath);
- } else {
- const ext = path.extname(item).toLowerCase();
-
- // Copy asset files
- if (assetExtensions.includes(ext)) {
- console.log(`Copying asset: ${srcItemPath} -> ${distItemPath}`);
- fs.copyFileSync(srcItemPath, distItemPath);
- }
- }
- });
-}
-
-try {
- console.log('Copying assets from src to dist...');
- copyAssets(srcDir, distDir);
- console.log('Asset copying completed successfully!');
-} catch (error) {
- console.error('Error copying assets:', error);
- process.exit(1);
-}
diff --git a/SerpentRace_Backend/scripts/deploy.bat b/SerpentRace_Backend/scripts/deploy.bat
deleted file mode 100644
index 465ad1dc..00000000
--- a/SerpentRace_Backend/scripts/deploy.bat
+++ /dev/null
@@ -1,233 +0,0 @@
-@echo off
-REM SerpentRace Backend Production Deployment Script for Windows
-REM This script handles the complete deployment process
-
-setlocal EnableDelayedExpansion
-
-set "SCRIPT_START=%TIME%"
-
-REM Colors simulation for Windows (using echo with different prefixes)
-set "LOG_PREFIX=[INFO]"
-set "ERROR_PREFIX=[ERROR]"
-set "WARN_PREFIX=[WARN]"
-
-:log
-echo %LOG_PREFIX% [%DATE% %TIME%] %~1
-goto :eof
-
-:error
-echo %ERROR_PREFIX% [%DATE% %TIME%] %~1
-goto :eof
-
-:warn
-echo %WARN_PREFIX% [%DATE% %TIME%] %~1
-goto :eof
-
-:check_env
-call :log "Checking environment variables..."
-
-set "required_vars=DB_HOST DB_PORT DB_USERNAME DB_PASSWORD DB_NAME JWT_SECRET REDIS_HOST REDIS_PORT"
-set "missing_vars="
-
-for %%v in (%required_vars%) do (
- call set "var_value=%%!%%v!%%"
- if "!var_value!"=="" (
- set "missing_vars=!missing_vars! %%v"
- )
-)
-
-if not "!missing_vars!"==" " (
- call :error "Missing required environment variables:!missing_vars!"
- call :error "Please set these variables before running the deployment"
- exit /b 1
-)
-
-call :log "All required environment variables are set"
-goto :eof
-
-:install_dependencies
-call :log "Installing production dependencies..."
-npm ci --only=production
-if !errorlevel! neq 0 (
- call :error "Failed to install dependencies"
- exit /b 1
-)
-call :log "Dependencies installed successfully"
-goto :eof
-
-:run_build
-call :log "Running production build..."
-npm run build:production
-if !errorlevel! neq 0 (
- call :error "Build failed"
- exit /b 1
-)
-call :log "Build completed successfully"
-goto :eof
-
-:test_database
-call :log "Testing database connectivity..."
-
-echo import { AppDataSource } from './src/Infrastructure/ormconfig'; > test-db-temp.ts
-echo. >> test-db-temp.ts
-echo async function testConnection() { >> test-db-temp.ts
-echo try { >> test-db-temp.ts
-echo await AppDataSource.initialize(); >> test-db-temp.ts
-echo console.log('â
Database connection successful'^); >> test-db-temp.ts
-echo await AppDataSource.destroy(); >> test-db-temp.ts
-echo process.exit(0^); >> test-db-temp.ts
-echo } catch (error^) { >> test-db-temp.ts
-echo console.error('â Database connection failed:', error^); >> test-db-temp.ts
-echo process.exit(1^); >> test-db-temp.ts
-echo } >> test-db-temp.ts
-echo } >> test-db-temp.ts
-echo. >> test-db-temp.ts
-echo testConnection(); >> test-db-temp.ts
-
-npx ts-node test-db-temp.ts
-set "db_test_result=!errorlevel!"
-del test-db-temp.ts 2>nul
-
-if !db_test_result! neq 0 (
- call :error "Database connectivity test failed"
- exit /b 1
-)
-
-call :log "Database connectivity test passed"
-goto :eof
-
-:test_redis
-call :log "Testing Redis connectivity..."
-
-echo import { createClient } from 'redis'; > test-redis-temp.ts
-echo. >> test-redis-temp.ts
-echo async function testRedis() { >> test-redis-temp.ts
-echo const client = createClient({ >> test-redis-temp.ts
-echo socket: { >> test-redis-temp.ts
-echo host: process.env.REDIS_HOST ^|^| 'localhost', >> test-redis-temp.ts
-echo port: parseInt(process.env.REDIS_PORT ^|^| '6379'^) >> test-redis-temp.ts
-echo } >> test-redis-temp.ts
-echo }^); >> test-redis-temp.ts
-echo. >> test-redis-temp.ts
-echo try { >> test-redis-temp.ts
-echo await client.connect(); >> test-redis-temp.ts
-echo await client.ping(); >> test-redis-temp.ts
-echo console.log('â
Redis connection successful'^); >> test-redis-temp.ts
-echo await client.disconnect(); >> test-redis-temp.ts
-echo process.exit(0^); >> test-redis-temp.ts
-echo } catch (error^) { >> test-redis-temp.ts
-echo console.error('â Redis connection failed:', error^); >> test-redis-temp.ts
-echo process.exit(1^); >> test-redis-temp.ts
-echo } >> test-redis-temp.ts
-echo } >> test-redis-temp.ts
-echo. >> test-redis-temp.ts
-echo testRedis(); >> test-redis-temp.ts
-
-npx ts-node test-redis-temp.ts
-set "redis_test_result=!errorlevel!"
-del test-redis-temp.ts 2>nul
-
-if !redis_test_result! neq 0 (
- call :warn "Redis connectivity test failed - continuing anyway"
-) else (
- call :log "Redis connectivity test passed"
-)
-goto :eof
-
-:setup_directories
-call :log "Setting up required directories..."
-if not exist "logs" mkdir logs
-if not exist "uploads" mkdir uploads
-call :log "Directories created"
-goto :eof
-
-:start_app
-call :log "Starting application for validation..."
-
-REM Start the app in background
-start /B "" npm start
-
-REM Wait for app to start
-timeout /t 10 /nobreak >nul
-
-REM Test if the health endpoint responds (using curl if available)
-set "PORT_VAR=!PORT!"
-if "!PORT_VAR!"=="" set "PORT_VAR=3000"
-
-curl -f http://localhost:!PORT_VAR!/health >nul 2>&1
-if !errorlevel! equ 0 (
- call :log "Application health check passed"
- REM Try to stop the background process (this is tricky in batch)
- taskkill /F /IM node.exe /FI "WINDOWTITLE eq npm start*" >nul 2>&1
-) else (
- call :error "Application health check failed"
- taskkill /F /IM node.exe /FI "WINDOWTITLE eq npm start*" >nul 2>&1
- exit /b 1
-)
-goto :eof
-
-:deploy
-call :log "đ Starting SerpentRace Backend production deployment..."
-
-call :check_env
-if !errorlevel! neq 0 exit /b 1
-
-call :install_dependencies
-if !errorlevel! neq 0 exit /b 1
-
-call :run_build
-if !errorlevel! neq 0 exit /b 1
-
-call :setup_directories
-if !errorlevel! neq 0 exit /b 1
-
-call :test_database
-if !errorlevel! neq 0 exit /b 1
-
-call :test_redis
-REM Redis test failure is not fatal
-
-if not "%SKIP_APP_TEST%"=="true" (
- call :start_app
- if !errorlevel! neq 0 exit /b 1
-) else (
- call :warn "Skipping application startup test"
-)
-
-call :log "đ Deployment completed successfully!"
-call :log "You can now start the application with: npm start"
-goto :eof
-
-:build_only
-call :log "Running build-only deployment..."
-call :check_env
-if !errorlevel! neq 0 exit /b 1
-call :install_dependencies
-if !errorlevel! neq 0 exit /b 1
-call :run_build
-if !errorlevel! neq 0 exit /b 1
-call :setup_directories
-call :log "Build-only deployment completed"
-goto :eof
-
-:test_connections
-call :log "Testing connections only..."
-call :check_env
-if !errorlevel! neq 0 exit /b 1
-call :test_database
-if !errorlevel! neq 0 exit /b 1
-call :test_redis
-call :log "Connection tests completed"
-goto :eof
-
-REM Main script logic
-if "%1"=="" goto deploy
-if "%1"=="deploy" goto deploy
-if "%1"=="build-only" goto build_only
-if "%1"=="test-connections" goto test_connections
-
-echo Usage: %0 [deploy^|build-only^|test-connections]
-echo deploy - Full deployment (default)
-echo build-only - Only build, skip tests
-echo test-connections - Test database and Redis connections
-exit /b 1
diff --git a/SerpentRace_Backend/scripts/deploy.sh b/SerpentRace_Backend/scripts/deploy.sh
deleted file mode 100644
index 4af6b641..00000000
--- a/SerpentRace_Backend/scripts/deploy.sh
+++ /dev/null
@@ -1,237 +0,0 @@
-#!/bin/bash
-
-# SerpentRace Backend Production Deployment Script
-# This script handles the complete deployment process
-
-set -e # Exit on any error
-
-# Colors for output
-RED='\033[0;31m'
-GREEN='\033[0;32m'
-YELLOW='\033[1;33m'
-BLUE='\033[0;34m'
-NC='\033[0m' # No Color
-
-log() {
- echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')] $1${NC}"
-}
-
-error() {
- echo -e "${RED}[$(date +'%Y-%m-%d %H:%M:%S')] ERROR: $1${NC}"
-}
-
-warn() {
- echo -e "${YELLOW}[$(date +'%Y-%m-%d %H:%M:%S')] WARNING: $1${NC}"
-}
-
-info() {
- echo -e "${BLUE}[$(date +'%Y-%m-%d %H:%M:%S')] INFO: $1${NC}"
-}
-
-# Check if required environment variables are set
-check_env() {
- log "Checking environment variables..."
-
- required_vars=(
- "DB_HOST"
- "DB_PORT"
- "DB_USERNAME"
- "DB_PASSWORD"
- "DB_NAME"
- "JWT_SECRET"
- "REDIS_HOST"
- "REDIS_PORT"
- )
-
- missing_vars=()
- for var in "${required_vars[@]}"; do
- if [ -z "${!var}" ]; then
- missing_vars+=("$var")
- fi
- done
-
- if [ ${#missing_vars[@]} -ne 0 ]; then
- error "Missing required environment variables: ${missing_vars[*]}"
- error "Please set these variables before running the deployment"
- exit 1
- fi
-
- log "All required environment variables are set"
-}
-
-# Install dependencies
-install_dependencies() {
- log "Installing production dependencies..."
- npm ci --only=production
- log "Dependencies installed successfully"
-}
-
-# Run the comprehensive build process
-run_build() {
- log "Running production build..."
- npm run build:production
- log "Build completed successfully"
-}
-
-# Test database connectivity
-test_database() {
- log "Testing database connectivity..."
-
- # Use a simple TypeScript script to test connection
- cat > /tmp/test-db.ts << 'EOF'
-import { AppDataSource } from './src/Infrastructure/ormconfig';
-
-async function testConnection() {
- try {
- await AppDataSource.initialize();
- console.log('â
Database connection successful');
- await AppDataSource.destroy();
- process.exit(0);
- } catch (error) {
- console.error('â Database connection failed:', error);
- process.exit(1);
- }
-}
-
-testConnection();
-EOF
-
- npx ts-node /tmp/test-db.ts || {
- error "Database connectivity test failed"
- exit 1
- }
-
- rm -f /tmp/test-db.ts
- log "Database connectivity test passed"
-}
-
-# Test Redis connectivity
-test_redis() {
- log "Testing Redis connectivity..."
-
- # Use a simple script to test Redis connection
- cat > /tmp/test-redis.ts << 'EOF'
-import { createClient } from 'redis';
-
-async function testRedis() {
- const client = createClient({
- socket: {
- host: process.env.REDIS_HOST || 'localhost',
- port: parseInt(process.env.REDIS_PORT || '6379')
- }
- });
-
- try {
- await client.connect();
- await client.ping();
- console.log('â
Redis connection successful');
- await client.disconnect();
- process.exit(0);
- } catch (error) {
- console.error('â Redis connection failed:', error);
- process.exit(1);
- }
-}
-
-testRedis();
-EOF
-
- npx ts-node /tmp/test-redis.ts || {
- warn "Redis connectivity test failed - continuing anyway"
- }
-
- rm -f /tmp/test-redis.ts
- log "Redis connectivity test completed"
-}
-
-# Create required directories
-setup_directories() {
- log "Setting up required directories..."
- mkdir -p logs
- mkdir -p uploads
- log "Directories created"
-}
-
-# Start the application (for testing)
-start_app() {
- log "Starting application for validation..."
-
- # Start the app in background and test if it responds
- npm start &
- APP_PID=$!
-
- # Wait for app to start
- sleep 10
-
- # Test if the health endpoint responds
- if curl -f http://localhost:${PORT:-3000}/health > /dev/null 2>&1; then
- log "Application health check passed"
- kill $APP_PID
- wait $APP_PID 2>/dev/null
- else
- error "Application health check failed"
- kill $APP_PID 2>/dev/null || true
- wait $APP_PID 2>/dev/null || true
- exit 1
- fi
-}
-
-# Main deployment function
-deploy() {
- log "đ Starting SerpentRace Backend production deployment..."
-
- # Check environment
- check_env
-
- # Install dependencies
- install_dependencies
-
- # Run build process
- run_build
-
- # Setup directories
- setup_directories
-
- # Test connections
- test_database
- test_redis
-
- # Test application startup
- if [ "${SKIP_APP_TEST}" != "true" ]; then
- start_app
- else
- warn "Skipping application startup test"
- fi
-
- log "đ Deployment completed successfully!"
- info "You can now start the application with: npm start"
-}
-
-# Handle script arguments
-case "${1:-deploy}" in
- "deploy")
- deploy
- ;;
- "build-only")
- log "Running build-only deployment..."
- check_env
- install_dependencies
- run_build
- setup_directories
- log "Build-only deployment completed"
- ;;
- "test-connections")
- log "Testing connections only..."
- check_env
- test_database
- test_redis
- log "Connection tests completed"
- ;;
- *)
- echo "Usage: $0 [deploy|build-only|test-connections]"
- echo " deploy - Full deployment (default)"
- echo " build-only - Only build, skip tests"
- echo " test-connections - Test database and Redis connections"
- exit 1
- ;;
-esac
diff --git a/SerpentRace_Backend/scripts/generate-migration.ts b/SerpentRace_Backend/scripts/generate-migration.ts
deleted file mode 100644
index 9ad0a8f3..00000000
--- a/SerpentRace_Backend/scripts/generate-migration.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import { execSync } from 'child_process';
-
-const migrationName = process.argv[2];
-
-if (!migrationName) {
- console.error('Please provide a migration name: npm run migration:full ');
- process.exit(1);
-}
-
-try {
- console.log(`Creating migration: ${migrationName}`);
- execSync(`npx ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli migration:create ./src/Infrastructure/Migrationsettings/${migrationName}`, { stdio: 'inherit' });
-
- console.log(`Generating migration: ${migrationName}`);
- execSync(`npx ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli -d ./src/Infrastructure/ormconfig.ts migration:generate ./src/Infrastructure/Migrations/${migrationName}`, { stdio: 'inherit' });
-
- console.log('Migration generated successfully!');
-
- console.log('Running migration...');
- execSync(`npx ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli -d ./src/Infrastructure/ormconfig.ts migration:run`, { stdio: 'inherit' });
-} catch (error) {
- if (error instanceof Error) {
- console.error('Migration failed:', error.message);
- } else {
- console.error('Migration failed:', error);
- }
- process.exit(1);
-}
\ No newline at end of file
diff --git a/SerpentRace_Backend/scripts/test-redis.ps1 b/SerpentRace_Backend/scripts/test-redis.ps1
deleted file mode 100644
index 18d8ecfa..00000000
--- a/SerpentRace_Backend/scripts/test-redis.ps1
+++ /dev/null
@@ -1,21 +0,0 @@
-# PowerShell script to start Redis and run tests
-Write-Host "Starting Redis with Docker Compose..." -ForegroundColor Green
-docker-compose up -d redis
-
-# Wait for Redis to be ready
-Write-Host "Waiting for Redis to be ready..." -ForegroundColor Yellow
-do {
- Write-Host "Checking Redis connection..." -ForegroundColor Gray
- $result = docker-compose exec redis redis-cli ping 2>$null
- if ($result -ne "PONG") {
- Start-Sleep -Seconds 2
- }
-} while ($result -ne "PONG")
-
-Write-Host "Redis is ready!" -ForegroundColor Green
-
-# Run Redis tests
-Write-Host "Running Redis tests..." -ForegroundColor Cyan
-npm test -- --testNamePattern="RedisService"
-
-Write-Host "Done!" -ForegroundColor Green
diff --git a/SerpentRace_Backend/scripts/test-redis.sh b/SerpentRace_Backend/scripts/test-redis.sh
deleted file mode 100644
index 791362ae..00000000
--- a/SerpentRace_Backend/scripts/test-redis.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-
-# Script to start Redis and run tests
-echo "Starting Redis with Docker Compose..."
-docker-compose up -d redis
-
-# Wait for Redis to be ready
-echo "Waiting for Redis to be ready..."
-until docker-compose exec redis redis-cli ping; do
- echo "Waiting for Redis..."
- sleep 2
-done
-
-echo "Redis is ready!"
-
-# Run Redis tests
-echo "Running Redis tests..."
-npm test -- --testNamePattern="RedisService"
-
-echo "Done!"
diff --git a/SerpentRace_Backend/src/Api/index.ts b/SerpentRace_Backend/src/Api/index.ts
deleted file mode 100644
index 5bcc6a6e..00000000
--- a/SerpentRace_Backend/src/Api/index.ts
+++ /dev/null
@@ -1,314 +0,0 @@
-import express from 'express';
-import { createServer } from 'http';
-import cookieParser from 'cookie-parser';
-import helmet from 'helmet';
-import { AppDataSource } from '../Infrastructure/ormconfig';
-import userRouter from './routers/userRouter';
-import organizationRouter from './routers/organizationRouter';
-import deckRouter from './routers/deckRouter';
-import chatRouter from './routers/chatRouter';
-import contactRouter from './routers/contactRouter';
-import adminRouter from './routers/adminRouter';
-import deckImportExportRouter from './routers/deckImportExportRouter';
-import gameRouter from './routers/gameRouter';
-import { LoggingService, logStartup, logConnection, logError, logRequest } from '../Application/Services/Logger';
-import { WebSocketService } from '../Application/Services/WebSocketService';
-import { GameWebSocketService } from '../Application/Services/GameWebSocketService';
-import { container } from '../Application/Services/DIContainer';
-import { GameRepository } from '../Infrastructure/Repository/GameRepository';
-import { UserRepository } from '../Infrastructure/Repository/UserRepository';
-import { RedisService } from '../Application/Services/RedisService';
-import { setupSwagger } from './swagger/swaggerUiSetup';
-
-const app = express();
-const httpServer = createServer(app);
-const PORT = process.env.PORT || 3000;
-const isDevelopment = process.env.NODE_ENV === 'development';
-
-const loggingService = LoggingService.getInstance();
-
-// Validate required environment variables in production
-if (process.env.NODE_ENV === 'production') {
- const requiredEnvVars = [
- 'JWT_SECRET',
- 'DB_PASSWORD',
- 'DB_HOST',
- 'DB_NAME',
- 'POSTGRES_PASSWORD'
- ];
-
- const missingVars = requiredEnvVars.filter(varName => !process.env[varName]);
-
- if (missingVars.length > 0) {
- logError('[FATAL] Missing required environment variables in production:', missingVars.join(', '));
- logError('[FATAL] Please configure all required environment variables in .env.server');
- process.exit(1);
- }
-
- // Check for placeholder values that haven't been changed
- if (process.env.JWT_SECRET && process.env.JWT_SECRET.includes('CHANGE_THIS')) {
- logError('[FATAL] JWT_SECRET still contains placeholder value. Please set a proper secret in .env.server');
- process.exit(1);
- }
-
- if (process.env.POSTGRES_PASSWORD && process.env.POSTGRES_PASSWORD.includes('CHANGE_THIS')) {
- logError('[FATAL] POSTGRES_PASSWORD still contains placeholder value. Please set a proper password in .env.server');
- process.exit(1);
- }
-}
-
-logStartup('SerpentRace Backend starting up', {
- environment: process.env.NODE_ENV || 'development',
- port: PORT,
- nodeVersion: process.version,
- chatInactivityTimeout: process.env.CHAT_INACTIVITY_TIMEOUT_MINUTES || '30'
-});
-
-app.use(helmet({
- contentSecurityPolicy: isDevelopment ? false : undefined
-}));
-
-app.use(express.json({ limit: '10mb' }));
-app.use(express.urlencoded({ extended: true, limit: '10mb' }));
-app.use(cookieParser());
-
-app.use(loggingService.requestLoggingMiddleware());
-
-app.use((req, res, next) => {
- const origin = req.headers.origin;
- const allowedOrigins = ['http://localhost:3000', 'http://localhost:3001', 'http://localhost:8080', process.env.FRONTEND_URL];
-
- if (!origin || allowedOrigins.includes(origin)) {
- res.setHeader('Access-Control-Allow-Origin', origin || '*');
- }
-
- res.setHeader('Access-Control-Allow-Credentials', 'true');
- res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
- res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, Cookie');
-
- if (req.method === 'OPTIONS') {
- res.status(200).end();
- return;
- }
-
- next();
-});
-
-if (isDevelopment) {
- app.use((req, res, next) => {
- logRequest(`${req.method} ${req.path}`, req, res);
- next();
- });
-}
-
-// Setup Swagger documentation
-setupSwagger(app);
-
-app.get('/', (req, res) => {
- res.json({
- service: 'SerpentRace Backend API',
- status: 'running',
- version: '1.0.0',
- endpoints: {
- swagger: '/api-docs',
- users: '/api/users',
- organizations: '/api/organizations',
- decks: '/api/decks',
- chats: '/api/chats',
- contacts: '/api/contacts',
- admin: '/api/admin',
- deckImportExport: '/api/deck-import-export',
- health: '/health'
- },
- websocket: {
- enabled: true,
- events: [
- 'chat:join', 'chat:leave', 'message:send',
- 'group:create', 'chat:direct', 'game:chat:create',
- 'chat:history'
- ]
- }
- });
-});
-
-app.get('/health', async (req, res) => {
- try {
- const isDbConnected = AppDataSource.isInitialized;
-
- res.json({
- status: 'healthy',
- timestamp: new Date().toISOString(),
- service: 'SerpentRace Backend API',
- version: '1.0.0',
- environment: process.env.NODE_ENV || 'development',
- database: {
- connected: isDbConnected,
- type: AppDataSource.options.type
- },
- websocket: {
- enabled: true
- },
- uptime: process.uptime()
- });
- } catch (error) {
- res.status(503).json({
- status: 'unhealthy',
- timestamp: new Date().toISOString(),
- error: 'Service health check failed'
- });
- }
-});
-
-// API Routes
-app.use('/api/users', userRouter);
-app.use('/api/organizations', organizationRouter);
-app.use('/api/decks', deckRouter);
-app.use('/api/chats', chatRouter);
-app.use('/api/contacts', contactRouter);
-app.use('/api/admin', adminRouter);
-app.use('/api/deck-import-export', deckImportExportRouter);
-app.use('/api/games', gameRouter);
-
-// Global error handler (must be after routes)
-app.use(loggingService.errorLoggingMiddleware());
-app.use((error: Error, req: express.Request, res: express.Response, next: express.NextFunction) => {
- logError('Global error handler caught unhandled error', error, req, res);
-
- // Don't expose internal error details in production
- const isDevelopment = process.env.NODE_ENV === 'development';
-
- res.status(500).json({
- error: 'Internal server error',
- timestamp: new Date().toISOString(),
- ...(isDevelopment && { details: error.message, stack: error.stack })
- });
-});
-
-// Handle 404 routes
-app.use((req: express.Request, res: express.Response) => {
- res.status(404).json({
- error: 'Route not found',
- path: req.originalUrl,
- method: req.method,
- timestamp: new Date().toISOString()
- });
-});
-
-// Initialize WebSocket service after database connection
-let webSocketService: WebSocketService;
-let gameWebSocketService: GameWebSocketService;
-
-// Initialize database connection
-AppDataSource.initialize()
- .then(() => {
- const dbOptions = AppDataSource.options as any;
- logConnection('Database connection established', 'postgresql', 'success', {
- type: dbOptions.type,
- host: dbOptions.host,
- database: dbOptions.database
- });
-
- // Initialize WebSocket service after database is connected
- webSocketService = new WebSocketService(httpServer);
- logStartup('WebSocket service initialized', {
- chatInactivityTimeout: process.env.CHAT_INACTIVITY_TIMEOUT_MINUTES || '30'
- });
-
- // Initialize Game WebSocket service for /game namespace via DIContainer
- container.setSocketIO(webSocketService['io']);
- gameWebSocketService = container.gameWebSocketService;
- logStartup('Game WebSocket service initialized for /game namespace');
-
- // Restore active games from snapshots (if any exist)
- gameWebSocketService.restoreAllActiveGames()
- .then(restoredCount => {
- if (restoredCount > 0) {
- logStartup(`Restored ${restoredCount} active game(s) from snapshots`);
- }
- })
- .catch(error => {
- logError('Failed to restore games from snapshots', error);
- });
- })
- .catch((error) => {
- const dbOptions = AppDataSource.options as any;
- logConnection('Database connection failed', 'postgresql', 'failure', {
- error: error.message,
- type: dbOptions.type,
- host: dbOptions.host,
- database: dbOptions.database
- });
- process.exit(1);
- });
-
-// Start server with WebSocket support
-const server = httpServer.listen(PORT, () => {
- logStartup('Server started successfully', {
- port: PORT,
- environment: process.env.NODE_ENV || 'development',
- timestamp: new Date().toISOString(),
- endpoints: {
- health: `/health`,
- swagger: `/api-docs`,
- users: `/api/users`,
- organizations: `/api/organizations`,
- decks: `/api/decks`,
- chats: `/api/chats`
- },
- websocket: {
- enabled: true,
- chatInactivityTimeout: `${process.env.CHAT_INACTIVITY_TIMEOUT_MINUTES || '30'} minutes`
- }
- });
-});
-
-// Graceful shutdown
-const gracefulShutdown = async (signal: string) => {
- logStartup(`Received ${signal}. Shutting down gracefully...`);
-
- // Snapshot all active games before shutdown
- if (gameWebSocketService) {
- try {
- const snapshotCount = await gameWebSocketService.snapshotAllActiveGames();
- logStartup(`Created ${snapshotCount} game snapshot(s) before shutdown`);
- } catch (error) {
- logError('Failed to snapshot games before shutdown', error as Error);
- }
- }
-
- server.close(() => {
- logStartup('HTTP server closed');
-
- if (AppDataSource.isInitialized) {
- AppDataSource.destroy()
- .then(() => {
- logConnection('Database connection closed', 'postgresql', 'success');
- process.exit(0);
- })
- .catch((error) => {
- logError('Error during database shutdown', error);
- process.exit(1);
- });
- } else {
- process.exit(0);
- }
- });
-};
-
-process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
-process.on('SIGINT', () => gracefulShutdown('SIGINT'));
-
-// Handle uncaught exceptions
-process.on('uncaughtException', (error) => {
- logError('Uncaught Exception - Server will shut down', error);
- process.exit(1);
-});
-
-// Handle unhandled promise rejections
-process.on('unhandledRejection', (reason, promise) => {
- logError('Unhandled Rejection - Server will shut down', new Error(String(reason)), undefined, undefined);
- process.exit(1);
-});
-
-// Export WebSocket services for game integration
-export { webSocketService, gameWebSocketService };
diff --git a/SerpentRace_Backend/src/Api/middleware/optionalAuth.ts b/SerpentRace_Backend/src/Api/middleware/optionalAuth.ts
deleted file mode 100644
index 05953518..00000000
--- a/SerpentRace_Backend/src/Api/middleware/optionalAuth.ts
+++ /dev/null
@@ -1,67 +0,0 @@
-import { Request, Response, NextFunction } from 'express';
-import { JWTService } from '../../Application/Services/JWTService';
-import { UserState } from '../../Domain/User/UserAggregate';
-import { logAuth, logWarning } from '../../Application/Services/Logger';
-
-interface AuthenticatedRequest extends Request {
- user?: {
- userId: string;
- authLevel: 0 | 1;
- userStatus: UserState;
- orgId: string | null;
- };
-}
-
-/**
- * Optional authentication middleware - extracts JWT data if present but doesn't require authentication
- * Used for endpoints that work for both authenticated and anonymous users
- */
-export const optionalAuth = (req: AuthenticatedRequest, res: Response, next: NextFunction) => {
- const jwtService = new JWTService();
-
- try {
- // Try to extract token from Authorization header or cookies
- const authHeader = req.headers.authorization;
- const token = authHeader?.startsWith('Bearer ')
- ? authHeader.substring(7)
- : req.cookies?.auth_token;
-
- if (token) {
- // If token exists, try to verify it
- const payload = jwtService.verify(req);
-
- if (payload) {
- req.user = {
- userId: payload.userId,
- authLevel: payload.authLevel,
- userStatus: payload.userStatus,
- orgId: payload.orgId || null
- };
-
- logAuth('Optional auth - user authenticated', payload.userId, {
- authLevel: payload.authLevel,
- userStatus: payload.userStatus,
- orgId: payload.orgId
- });
- } else {
- logWarning('Optional auth - invalid token provided', {
- hasToken: true,
- tokenLength: token.length
- });
- }
- }
-
- // Continue regardless of authentication status
- next();
-
- } catch (error) {
- // Log the error but continue without authentication
- logWarning('Optional auth - error processing token', {
- error: error instanceof Error ? error.message : String(error),
- hasAuthHeader: !!req.headers.authorization,
- hasCookie: !!req.cookies?.auth_token
- });
-
- next();
- }
-};
\ No newline at end of file
diff --git a/SerpentRace_Backend/src/Api/routers/adminRouter.ts b/SerpentRace_Backend/src/Api/routers/adminRouter.ts
deleted file mode 100644
index 4226687a..00000000
--- a/SerpentRace_Backend/src/Api/routers/adminRouter.ts
+++ /dev/null
@@ -1,1141 +0,0 @@
-import express, { Request, Response } from 'express';
-import multer from 'multer';
-import { DIContainer } from '../../Application/Services/DIContainer';
-import { adminRequired } from '../../Application/Services/AuthMiddleware';
-import { UserState } from '../../Domain/User/UserAggregate';
-import { ValidationMiddleware } from '../../Application/Services/ValidationMiddleware';
-import { ErrorResponseService } from '../../Application/Services/ErrorResponseService';
-import { AdminAuditService } from '../../Application/Services/AdminBypassService';
-import { webSocketService } from '../index';
-import { logRequest, logError, logWarning, logAuth } from '../../Application/Services/Logger';
-
-// Extend Express Request interface for file uploads
-declare global {
- namespace Express {
- interface Request {
- file?: Express.Multer.File;
- }
- }
-}
-
-const router = express.Router();
-const container = DIContainer.getInstance();
-
-// Configure multer for file uploads
-const upload = multer({
- storage: multer.memoryStorage(),
- limits: {
- fileSize: 10 * 1024 * 1024, // 10MB limit
- },
- fileFilter: (req: any, file: any, cb: any) => {
- if (file.mimetype === 'application/json' || file.originalname.endsWith('.spr')) {
- cb(null, true);
- } else {
- cb(new Error('Only JSON and .spr files are allowed'));
- }
- }
-});
-
-// Helper function to extract language from Accept-Language header
-function extractLanguageFromAcceptHeader(acceptLanguage: string): string | null {
- if (!acceptLanguage) return null;
-
- const languages = acceptLanguage.split(',');
- if (languages.length > 0) {
- const primaryLanguage = languages[0].split(';')[0].trim().substring(0, 2);
- return primaryLanguage;
- }
-
- return null;
-}
-
-// =============================================================================
-// USER MANAGEMENT ROUTES
-// =============================================================================
-
-// Get users with pagination (RECOMMENDED)
-router.get('/users/page/:from/:to', adminRequired, async (req: Request, res: Response) => {
- try {
- const from = parseInt(req.params.from);
- const to = parseInt(req.params.to);
- const includeDeleted = req.query.includeDeleted === 'true';
-
- if (isNaN(from) || isNaN(to) || from < 0 || to < from) {
- return res.status(400).json({
- error: 'Invalid pagination parameters. From and to must be valid numbers with from <= to.'
- });
- }
-
- const limit = to - from + 1;
- if (limit > 100) {
- return res.status(400).json({
- error: 'Page size too large. Maximum 100 records per request.'
- });
- }
-
- logRequest('Admin paginated users endpoint accessed', req, res, { from, to, includeDeleted });
-
- const result = await container.getUsersByPageQueryHandler.execute({
- from,
- to,
- includeDeleted
- });
-
- const response = {
- users: result.users,
- pagination: {
- from,
- to,
- returned: result.users.length,
- totalCount: result.totalCount,
- includeDeleted
- }
- };
-
- logRequest('Admin users retrieved successfully', req, res, {
- returnedUsers: result.users.length,
- totalCount: result.totalCount,
- from,
- to,
- includeDeleted
- });
-
- return res.status(200).json(response);
- } catch (error: any) {
- logError('Error in admin get users endpoint', error, req, res);
- return res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-// Get user by ID including soft-deleted ones
-router.get('/users/:userId',
- adminRequired,
- ValidationMiddleware.validateUUIDFormat(['userId']),
- async (req: Request, res: Response) => {
- try {
- const targetUserId = req.params.userId;
- const includeDeleted = req.query.includeDeleted === 'true';
-
- logRequest('Admin get user by id endpoint accessed', req, res, { targetUserId, includeDeleted });
-
- const user = includeDeleted
- ? await container.userRepository.findByIdIncludingDeleted(targetUserId)
- : await container.userRepository.findById(targetUserId);
-
- if (!user) {
- logWarning('User not found', { targetUserId, includeDeleted }, req, res);
- return res.status(404).json({ error: 'User not found' });
- }
-
- logRequest('Admin user retrieved successfully', req, res, {
- targetUserId,
- username: user.username,
- includeDeleted
- });
-
- res.json(user);
- } catch (error) {
- logError('Admin get user by id endpoint error', error as Error, req, res);
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-// Search users including soft-deleted ones
-router.get('/users/search/:searchTerm',
- adminRequired,
- ValidationMiddleware.validateStringLength({ searchTerm: { min: 2, max: 100 } }),
- async (req: Request, res: Response) => {
- try {
- const { searchTerm } = req.params;
- const includeDeleted = req.query.includeDeleted === 'true';
-
- logRequest('Admin search users endpoint accessed', req, res, { searchTerm, includeDeleted });
-
- const users = includeDeleted
- ? await container.userRepository.searchIncludingDeleted(searchTerm)
- : await container.userRepository.search(searchTerm);
-
- logRequest('Admin user search completed', req, res, {
- searchTerm,
- resultCount: Array.isArray(users) ? users.length : (users.totalCount || 0),
- includeDeleted
- });
-
- res.json(users);
- } catch (error) {
- logError('Admin search users endpoint error', error as Error, req, res);
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-// Update any user (admin only)
-router.patch('/users/:userId',
- adminRequired,
- ValidationMiddleware.validateUUIDFormat(['userId']),
- async (req: Request, res: Response) => {
- try {
- const targetUserId = req.params.userId;
- const adminUserId = (req as any).user.userId;
-
- logRequest('Admin update user endpoint accessed', req, res, {
- adminUserId,
- targetUserId,
- fieldsToUpdate: Object.keys(req.body)
- });
-
- const result = await container.updateUserCommandHandler.execute({ id: targetUserId, ...req.body });
-
- if (!result) {
- return res.status(404).json({ error: 'User not found' });
- }
-
- logRequest('User updated by admin', req, res, {
- adminUserId,
- targetUserId,
- username: result.username
- });
-
- res.json(result);
-
- } catch (error) {
- logError('Admin update user endpoint error', error as Error, req, res);
-
- if (error instanceof Error) {
- if (error.message.includes('already exists')) {
- return res.status(409).json({ error: error.message });
- }
- if (error.message.includes('validation')) {
- return res.status(400).json({ error: error.message });
- }
- }
-
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-// Activate user (admin only)
-router.post('/users/:userId/activate',
- adminRequired,
- ValidationMiddleware.validateUUIDFormat(['userId']),
- async (req: Request, res: Response) => {
- try {
- const targetUserId = req.params.userId;
- const adminUserId = (req as any).user.userId;
-
- logRequest('Admin activate user endpoint accessed', req, res, { adminUserId, targetUserId });
-
- const result = await container.activateUserCommandHandler.execute({ id: targetUserId });
-
- if (!result) {
- return res.status(404).json({ error: 'User not found' });
- }
-
- logAuth('User activated by admin', targetUserId, { adminUserId }, req, res);
- res.json({ message: 'User activated successfully', user: result });
-
- } catch (error) {
- logError('Admin activate user endpoint error', error as Error, req, res);
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-// Deactivate user (admin only)
-router.post('/users/:userId/deactivate',
- adminRequired,
- ValidationMiddleware.validateUUIDFormat(['userId']),
- async (req: Request, res: Response) => {
- try {
- const targetUserId = req.params.userId;
- const adminUserId = (req as any).user.userId;
-
- logRequest('Deactivate user endpoint accessed', req, res, { adminUserId, targetUserId });
-
- const result = await container.deactivateUserCommandHandler.execute({ id: targetUserId });
-
- if (!result) {
- return res.status(404).json({ error: 'User not found' });
- }
-
- logAuth('User deactivated by admin', targetUserId, { adminUserId }, req, res);
- res.json({ message: 'User deactivated successfully', user: result });
-
- } catch (error) {
- logError('Deactivate user endpoint error', error as Error, req, res);
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-// Delete user (admin only)
-router.delete('/users/:userId',
- adminRequired,
- ValidationMiddleware.validateUUIDFormat(['userId']),
- async (req: Request, res: Response) => {
- try {
- const targetUserId = req.params.userId;
- const adminUserId = (req as any).user.userId;
- const softDelete = req.query.soft === 'true' || req.query.soft === undefined;
-
- logRequest('Delete user endpoint accessed', req, res, { adminUserId, targetUserId, softDelete });
-
- const result = await container.deleteUserCommandHandler.execute({ id: targetUserId, soft: softDelete });
-
- if (!result) {
- return res.status(404).json({ error: 'User not found' });
- }
-
- logAuth('User deleted by admin', targetUserId, { adminUserId }, req, res);
- res.json({ message: 'User deleted successfully' });
-
- } catch (error) {
- logError('Delete user endpoint error', error as Error, req, res);
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-// =============================================================================
-// DECK MANAGEMENT ROUTES
-// =============================================================================
-
-// Get decks by page (admin only) - RECOMMENDED
-router.get('/decks/page/:from/:to', adminRequired, async (req: Request, res: Response) => {
- try {
- const from = parseInt(req.params.from);
- const to = parseInt(req.params.to);
- const includeDeleted = req.query.includeDeleted === 'true';
-
- if (isNaN(from) || isNaN(to) || from < 0 || to < from) {
- return res.status(400).json({ error: 'Invalid page parameters. "from" and "to" must be valid numbers with to >= from >= 0' });
- }
-
- logRequest('Admin get decks by page endpoint accessed', req, res, { from, to, includeDeleted });
-
- // For admin, we need to pass admin context to get unrestricted decks
- const adminUserId = (req as any).user.userId;
- const result = await container.getDecksByPageQueryHandler.execute({
- userId: adminUserId,
- userOrgId: undefined,
- isAdmin: true,
- from,
- to,
- includeDeleted
- });
-
- logRequest('Admin decks page retrieved successfully', req, res, {
- from,
- to,
- count: result.decks.length,
- total: result.totalCount,
- includeDeleted
- });
-
- res.json(result);
- } catch (error) {
- logError('Admin get decks by page endpoint error', error as Error, req, res);
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-// Get deck by ID including soft-deleted ones
-router.get('/decks/:id', adminRequired, async (req: Request, res: Response) => {
- try {
- const { id } = req.params;
- const includeDeleted = req.query.includeDeleted === 'true';
-
- logRequest('Admin get deck by id endpoint accessed', req, res, { deckId: id, includeDeleted });
-
- const deck = includeDeleted
- ? await container.deckRepository.findByIdIncludingDeleted(id)
- : await container.deckRepository.findById(id);
-
- if (!deck) {
- logWarning('Deck not found', { deckId: id, includeDeleted }, req, res);
- return res.status(404).json({ error: 'Deck not found' });
- }
-
- logRequest('Admin deck retrieved successfully', req, res, { deckId: id, includeDeleted });
- res.json(deck);
- } catch (error) {
- logError('Admin get deck by id endpoint error', error as Error, req, res);
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-// Search decks including soft-deleted ones
-router.get('/decks/search/:searchTerm', adminRequired, async (req: Request, res: Response) => {
- try {
- const { searchTerm } = req.params;
- const includeDeleted = req.query.includeDeleted === 'true';
-
- logRequest('Admin search decks endpoint accessed', req, res, { searchTerm, includeDeleted });
-
- const decks = includeDeleted
- ? await container.deckRepository.searchIncludingDeleted(searchTerm)
- : await container.deckRepository.search(searchTerm);
-
- logRequest('Admin deck search completed', req, res, {
- searchTerm,
- resultCount: Array.isArray(decks) ? decks.length : (decks.totalCount || 0),
- includeDeleted
- });
-
- res.json(decks);
- } catch (error) {
- logError('Admin search decks endpoint error', error as Error, req, res);
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-//modify deck (admin only)
-router.patch('/decks/:id', adminRequired, async (req: Request, res: Response) => {
- try {
- const deckId = req.params.id;
- const adminUserId = (req as any).user.userId;
- logRequest('Admin update deck endpoint accessed', req, res, { deckId, adminUserId, updateFields: Object.keys(req.body) });
- const result = await container.updateDeckCommandHandler.execute({ id: deckId, userstate: 1 , ...req.body});
- logRequest('Deck updated successfully by admin', req, res, { deckId, adminUserId });
- res.json(result);
- } catch (error) {
- logError('Admin update deck endpoint error', error as Error, req, res);
- if (error instanceof Error && error.message.includes('not found')) {
- return res.status(404).json({ error: `Deck not found` });
- }
- if (error instanceof Error && (error.message.includes('duplicate') || error.message.includes('unique constraint'))) {
- return res.status(409).json({ error: 'Deck with this name already exists' });
- }
- if (error instanceof Error && error.message.includes('validation')) {
- return res.status(400).json({ error: 'Invalid input data', details: error.message });
- }
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-// Hard delete deck (admin only)
-router.delete('/decks/:id/hard', adminRequired, async (req: Request, res: Response) => {
- try {
- const adminUserId = (req as any).user.userId;
- const deckId = req.params.id;
- logRequest('Admin hard delete deck endpoint accessed', req, res, { deckId });
-
- const result = await container.deleteDeckCommandHandler.execute({ userid: adminUserId, authLevel: 1, id: deckId, soft: false });
-
- logRequest('Admin deck hard delete successful', req, res, { deckId, success: result });
- res.json({ success: result });
- } catch (error) {
- logError('Admin hard delete deck endpoint error', error as Error, req, res);
-
- if (error instanceof Error && error.message.includes('not found')) {
- return res.status(404).json({ error: 'Deck not found' });
- }
-
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-// =============================================================================
-// ORGANIZATION MANAGEMENT ROUTES
-// =============================================================================
-
-// Create organization (admin only)
-router.post('/organizations', adminRequired, async (req: Request, res: Response) => {
- try {
- const adminUserId = (req as any).user.userId;
- logRequest('Admin create organization endpoint accessed', req, res, { name: req.body.name, adminUserId });
-
- const result = await container.createOrganizationCommandHandler.execute(req.body);
-
- AdminAuditService.logAdminAction('CREATE_ORGANIZATION', adminUserId, {
- targetType: 'organization',
- targetId: result.id,
- operation: 'create',
- changes: req.body
- }, req, res);
-
- logRequest('Admin organization created successfully', req, res, { organizationId: result.id, name: req.body.name, adminUserId });
- res.json(result);
- } catch (error) {
- logError('Admin create organization endpoint error', error as Error, req, res);
-
- if (error instanceof Error && (error.message.includes('duplicate') || error.message.includes('unique constraint'))) {
- return res.status(409).json({ error: 'Organization with this name already exists' });
- }
-
- if (error instanceof Error && error.message.includes('validation')) {
- return res.status(400).json({ error: 'Invalid input data', details: error.message });
- }
-
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-// Update organization (admin only) - NEW ENDPOINT
-router.patch('/organizations/:id', adminRequired, async (req: Request, res: Response) => {
- try {
- const organizationId = req.params.id;
- const adminUserId = (req as any).user.userId;
-
- logRequest('Admin update organization endpoint accessed', req, res, {
- adminUserId,
- organizationId,
- fieldsToUpdate: Object.keys(req.body)
- });
-
- const result = await container.updateOrganizationCommandHandler.execute({
- id: organizationId,
- ...req.body
- });
-
- if (!result) {
- return res.status(404).json({ error: 'Organization not found' });
- }
-
- AdminAuditService.logAdminAction('UPDATE_ORGANIZATION', adminUserId, {
- targetType: 'organization',
- targetId: organizationId,
- operation: 'update',
- changes: req.body,
- sensitive: req.body.maxOrganizationalDecks !== undefined
- }, req, res);
-
- logRequest('Organization updated by admin', req, res, {
- adminUserId,
- organizationId,
- organizationName: result.name
- });
-
- res.json(result);
-
- } catch (error) {
- logError('Admin update organization endpoint error', error as Error, req, res);
-
- if (error instanceof Error) {
- if (error.message.includes('already exists')) {
- return res.status(409).json({ error: error.message });
- }
- if (error.message.includes('validation')) {
- return res.status(400).json({ error: error.message });
- }
- }
-
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-// Get organizations by page (admin only) - RECOMMENDED
-router.get('/organizations/page/:from/:to', adminRequired, async (req: Request, res: Response) => {
- try {
- const from = parseInt(req.params.from);
- const to = parseInt(req.params.to);
- const includeDeleted = req.query.includeDeleted === 'true';
-
- if (isNaN(from) || isNaN(to) || from < 0 || to < from) {
- return res.status(400).json({ error: 'Invalid page parameters. "from" and "to" must be valid numbers with to >= from >= 0' });
- }
-
- logRequest('Admin get organizations by page endpoint accessed', req, res, { from, to, includeDeleted });
-
- const result = await container.getOrganizationsByPageQueryHandler.execute({
- from,
- to,
- includeDeleted
- });
-
- logRequest('Admin organizations page retrieved successfully', req, res, {
- from,
- to,
- count: result.organizations.length,
- total: result.totalCount,
- includeDeleted
- });
-
- res.json(result);
- } catch (error) {
- logError('Admin get organizations by page endpoint error', error as Error, req, res);
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-// Get organization by ID including soft-deleted ones
-router.get('/organizations/:id', adminRequired, async (req: Request, res: Response) => {
- try {
- const organizationId = req.params.id;
- const includeDeleted = req.query.includeDeleted === 'true';
-
- logRequest('Admin get organization by id endpoint accessed', req, res, { organizationId, includeDeleted });
-
- const organization = includeDeleted
- ? await container.organizationRepository.findByIdIncludingDeleted(organizationId)
- : await container.organizationRepository.findById(organizationId);
-
- if (!organization) {
- logWarning('Organization not found', { organizationId, includeDeleted }, req, res);
- return res.status(404).json({ error: 'Organization not found' });
- }
-
- logRequest('Admin organization retrieved successfully', req, res, { organizationId, includeDeleted });
- res.json(organization);
- } catch (error) {
- logError('Admin get organization by id endpoint error', error as Error, req, res);
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-// Search organizations including soft-deleted ones
-router.get('/organizations/search/:searchTerm', adminRequired, async (req: Request, res: Response) => {
- try {
- const { searchTerm } = req.params;
- const includeDeleted = req.query.includeDeleted === 'true';
-
- logRequest('Admin search organizations endpoint accessed', req, res, { searchTerm, includeDeleted });
-
- const organizations = includeDeleted
- ? await container.organizationRepository.searchIncludingDeleted(searchTerm)
- : await container.organizationRepository.search(searchTerm);
-
- logRequest('Admin organization search completed', req, res, {
- searchTerm,
- resultCount: Array.isArray(organizations) ? organizations.length : (organizations.totalCount || 0),
- includeDeleted
- });
-
- res.json(organizations);
- } catch (error) {
- logError('Admin search organizations endpoint error', error as Error, req, res);
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-// Soft delete organization (admin only)
-router.delete('/organizations/:id', adminRequired, async (req: Request, res: Response) => {
- try {
- const organizationId = req.params.id;
- logRequest('Admin soft delete organization endpoint accessed', req, res, { organizationId });
-
- const result = await container.deleteOrganizationCommandHandler.execute({ id: organizationId, soft: true });
-
- logRequest('Admin organization soft delete successful', req, res, { organizationId, success: result });
- res.json({ success: result });
- } catch (error) {
- logError('Admin soft delete organization endpoint error', error as Error, req, res);
-
- if (error instanceof Error && error.message.includes('not found')) {
- return res.status(404).json({ error: 'Organization not found' });
- }
-
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-// Hard delete organization (admin only)
-router.delete('/organizations/:id/hard', adminRequired, async (req: Request, res: Response) => {
- try {
- const organizationId = req.params.id;
- logRequest('Admin hard delete organization endpoint accessed', req, res, { organizationId });
-
- const result = await container.deleteOrganizationCommandHandler.execute({ id: organizationId, soft: false });
-
- logRequest('Admin organization hard delete successful', req, res, { organizationId, success: result });
- res.json({ success: result });
- } catch (error) {
- logError('Admin hard delete organization endpoint error', error as Error, req, res);
-
- if (error instanceof Error && error.message.includes('not found')) {
- return res.status(404).json({ error: 'Organization not found' });
- }
-
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-// =============================================================================
-// CHAT MANAGEMENT ROUTES
-// =============================================================================
-
-// Get chats with pagination (RECOMMENDED)
-router.get('/chats/page/:from/:to', adminRequired, async (req: Request, res: Response) => {
- try {
- const from = parseInt(req.params.from);
- const to = parseInt(req.params.to);
- const includeDeleted = req.query.includeDeleted === 'true';
-
- if (isNaN(from) || isNaN(to) || from < 0 || to < from) {
- return res.status(400).json({
- error: 'Invalid pagination parameters. From and to must be valid numbers with from <= to.'
- });
- }
-
- const limit = to - from + 1;
- if (limit > 100) {
- return res.status(400).json({
- error: 'Page size too large. Maximum 100 records per request.'
- });
- }
-
- logRequest('Admin paginated chats endpoint accessed', req, res, { from, to, includeDeleted });
-
- const result = await container.getChatsByPageQueryHandler.execute({
- from,
- to,
- includeDeleted
- });
-
- const response = {
- chats: result.chats,
- pagination: {
- from,
- to,
- returned: result.chats.length,
- totalCount: result.totalCount,
- includeDeleted
- }
- };
-
- logRequest('Admin chats retrieved successfully', req, res, {
- returnedChats: result.chats.length,
- totalCount: result.totalCount,
- from,
- to,
- includeDeleted
- });
-
- return res.status(200).json(response);
- } catch (error: any) {
- logError('Error in admin get chats endpoint', error, req, res);
- return res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-// Get chat by ID including soft-deleted ones
-router.get('/chats/:id', adminRequired, async (req: Request, res: Response) => {
- try {
- const { id } = req.params;
- const includeDeleted = req.query.includeDeleted === 'true';
-
- logRequest('Admin get chat by id endpoint accessed', req, res, { chatId: id, includeDeleted });
-
- const chat = includeDeleted
- ? await container.chatRepository.findByIdIncludingDeleted(id)
- : await container.chatRepository.findById(id);
-
- if (!chat) {
- logWarning('Chat not found', { chatId: id, includeDeleted }, req, res);
- return res.status(404).json({ error: 'Chat not found' });
- }
-
- logRequest('Admin chat retrieved successfully', req, res, { chatId: id, includeDeleted });
- res.json(chat);
- } catch (error) {
- logError('Admin get chat by id endpoint error', error as Error, req, res);
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-// =============================================================================
-// CONTACT MANAGEMENT ROUTES
-// =============================================================================
-
-// Get contacts by page (admin only) - RECOMMENDED (already exists, enhanced)
-router.get('/contacts/page/:from/:to', adminRequired, async (req: Request, res: Response) => {
- try {
- const from = parseInt(req.params.from);
- const to = parseInt(req.params.to);
- const includeDeleted = req.query.includeDeleted === 'true';
-
- if (isNaN(from) || isNaN(to) || from < 0 || to < from) {
- return res.status(400).json({ error: 'Invalid page parameters. "from" and "to" must be valid numbers with to >= from >= 0' });
- }
-
- logRequest('Admin get contacts by page endpoint accessed', req, res, { from, to, includeDeleted });
-
- const result = includeDeleted
- ? await container.contactRepository.findByPageIncludingDeleted(from, to)
- : await container.contactRepository.findByPage(from, to);
-
- logRequest('Admin contacts page retrieved successfully', req, res, {
- from,
- to,
- count: result.contacts.length,
- total: result.totalCount,
- includeDeleted
- });
-
- res.json(result);
- } catch (error) {
- logError('Admin get contacts by page endpoint error', error as Error, req, res);
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-// Get contact by ID (admin only)
-router.get('/contacts/:id', adminRequired, async (req: Request, res: Response) => {
- try {
- const contactId = req.params.id;
- const includeDeleted = req.query.includeDeleted === 'true';
-
- logRequest('Admin get contact by ID endpoint accessed', req, res, { contactId, includeDeleted });
-
- const result = includeDeleted
- ? await container.contactRepository.findByIdIncludingDeleted(contactId)
- : await container.getContactByIdQueryHandler.execute({ id: contactId });
-
- if (!result) {
- logRequest('Contact not found', req, res, { contactId, includeDeleted });
- return res.status(404).json({ error: 'Contact not found' });
- }
-
- logRequest('Admin contact retrieved successfully', req, res, { contactId, includeDeleted });
- res.json(result);
- } catch (error) {
- logError('Admin get contact by ID endpoint error', error as Error, req, res);
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-// Search contacts including soft-deleted ones (admin only)
-router.get('/contacts/search/:searchTerm', adminRequired, async (req: Request, res: Response) => {
- try {
- const { searchTerm } = req.params;
- const includeDeleted = req.query.includeDeleted === 'true';
-
- logRequest('Admin search contacts endpoint accessed', req, res, { searchTerm, includeDeleted });
-
- const contacts = includeDeleted
- ? await container.contactRepository.searchIncludingDeleted(searchTerm)
- : await container.contactRepository.search(searchTerm);
-
- logRequest('Admin contact search completed', req, res, {
- searchTerm,
- resultCount: contacts.length,
- includeDeleted
- });
-
- res.json(contacts);
- } catch (error) {
- logError('Admin search contacts endpoint error', error as Error, req, res);
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-// Respond to contact (admin only)
-router.put('/contacts/:id/respond', adminRequired, async (req: Request, res: Response) => {
- try {
- const contactId = req.params.id;
- const adminUserId = (req as any).user.userId;
- const { adminResponse, sendEmail, language } = req.body;
-
- if (!adminResponse) {
- return res.status(400).json({ error: 'Admin response is required' });
- }
-
- // Determine language from body, headers, or default to English
- let selectedLanguage = language;
- if (!selectedLanguage) {
- // Try to get language from Accept-Language header
- const acceptLanguage = req.headers['accept-language'] as string;
- // Try to get language from custom headers (common frontend patterns)
- const regionHeader = req.headers['x-region'] as string;
- const languageHeader = req.headers['x-language'] as string;
- const localeHeader = req.headers['x-locale'] as string;
-
- selectedLanguage = languageHeader ||
- localeHeader ||
- regionHeader ||
- extractLanguageFromAcceptHeader(acceptLanguage) ||
- 'en';
- }
-
- // Validate and normalize language parameter
- if (!['en', 'hu', 'de'].includes(selectedLanguage.toLowerCase())) {
- selectedLanguage = 'en'; // Fallback to English for unsupported languages
- } else {
- selectedLanguage = selectedLanguage.toLowerCase();
- }
-
- logRequest('Admin respond to contact endpoint accessed', req, res, {
- contactId,
- adminUserId,
- sendEmail,
- language: selectedLanguage,
- headerLanguage: req.headers['accept-language'] || req.headers['x-language'] || 'none'
- });
-
- // Update contact with response
- const result = await container.updateContactCommandHandler.execute({
- id: contactId,
- adminResponse,
- respondedBy: adminUserId
- });
-
- if (!result) {
- logWarning('Contact not found for response', { contactId }, req, res);
- return res.status(404).json({ error: 'Contact not found' });
- }
-
- // Send email if requested
- let emailSent = false;
- let emailError = null;
-
- if (sendEmail === true && adminResponse) {
- try {
- await container.contactEmailService.sendResponse({
- to: result.email,
- message: adminResponse,
- contactId: contactId,
- adminUserId: adminUserId,
- contactName: result.name,
- contactType: result.type,
- originalMessage: result.txt,
- language: selectedLanguage
- });
- emailSent = true;
-
- logRequest('Contact response email sent successfully', req, res, {
- contactId,
- recipientEmail: result.email,
- language: selectedLanguage
- });
- } catch (emailErr) {
- emailError = emailErr instanceof Error ? emailErr.message : 'Email sending failed';
- logError('Contact response email failed', emailErr as Error, req, res);
- }
- }
-
- AdminAuditService.logAdminAction('RESPOND_TO_CONTACT', adminUserId, {
- targetType: 'contact',
- targetId: contactId,
- operation: 'update',
- changes: { adminResponse, sendEmail, language: selectedLanguage },
- metadata: { emailSent, emailError }
- }, req, res);
-
- logRequest('Admin contact response saved successfully', req, res, {
- contactId,
- sendEmail,
- emailSent,
- language: selectedLanguage
- });
-
- res.json({
- success: true,
- message: 'Response saved successfully',
- contact: result,
- emailSent,
- emailError: emailSent ? null : emailError
- });
- } catch (error) {
- logError('Admin respond to contact endpoint error', error as Error, req, res);
-
- if (error instanceof Error && error.message.includes('not found')) {
- return res.status(404).json({ error: 'Contact not found' });
- }
-
- if (error instanceof Error && error.message.includes('validation')) {
- return res.status(400).json({ error: 'Invalid input data', details: error.message });
- }
-
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-// Resend contact email (admin only) - NEW ENDPOINT
-router.post('/contacts/:id/resend-email', adminRequired, async (req: Request, res: Response) => {
- try {
- const contactId = req.params.id;
- const adminUserId = (req as any).user.userId;
- const { language } = req.body;
-
- logRequest('Admin resend contact email endpoint accessed', req, res, {
- contactId,
- adminUserId,
- language
- });
-
- // Get contact details
- const contact = await container.getContactByIdQueryHandler.execute({ id: contactId });
-
- if (!contact) {
- return res.status(404).json({ error: 'Contact not found' });
- }
-
- if (!contact.adminResponse) {
- return res.status(400).json({ error: 'No admin response found to resend' });
- }
-
- const selectedLanguage = language || 'en';
-
- try {
- await container.contactEmailService.sendResponse({
- to: contact.email,
- message: contact.adminResponse,
- contactId: contactId,
- adminUserId: adminUserId,
- contactName: contact.name,
- contactType: contact.type,
- originalMessage: contact.txt,
- language: selectedLanguage
- });
-
- AdminAuditService.logAdminAction('RESEND_CONTACT_EMAIL', adminUserId, {
- targetType: 'contact',
- targetId: contactId,
- operation: 'create',
- metadata: { language: selectedLanguage, action: 'resend' }
- }, req, res);
-
- logRequest('Contact email resent successfully', req, res, {
- contactId,
- recipientEmail: contact.email,
- language: selectedLanguage
- });
-
- res.json({
- success: true,
- message: 'Email resent successfully'
- });
- } catch (emailErr) {
- logError('Contact email resend failed', emailErr as Error, req, res);
- res.status(500).json({
- error: 'Failed to resend email',
- details: emailErr instanceof Error ? emailErr.message : 'Unknown error'
- });
- }
- } catch (error) {
- logError('Admin resend contact email endpoint error', error as Error, req, res);
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-// Soft delete contact (admin only) - NEW ENDPOINT
-router.delete('/contacts/:id', adminRequired, async (req: Request, res: Response) => {
- try {
- const contactId = req.params.id;
- const adminUserId = (req as any).user.userId;
-
- logRequest('Admin soft delete contact endpoint accessed', req, res, { contactId, adminUserId });
-
- const result = await container.deleteContactCommandHandler.execute({
- id: contactId,
- hard: false
- });
-
- AdminAuditService.logAdminAction('SOFT_DELETE_CONTACT', adminUserId, {
- targetType: 'contact',
- targetId: contactId,
- operation: 'update'
- }, req, res);
-
- logAuth('Contact soft deleted by admin', contactId, { adminUserId }, req, res);
- res.json({ success: result });
- } catch (error) {
- logError('Admin soft delete contact endpoint error', error as Error, req, res);
-
- if (error instanceof Error && error.message.includes('not found')) {
- return res.status(404).json({ error: 'Contact not found' });
- }
-
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-// Hard delete contact (admin only) - NEW ENDPOINT
-router.delete('/contacts/:id/hard', adminRequired, async (req: Request, res: Response) => {
- try {
- const contactId = req.params.id;
- const adminUserId = (req as any).user.userId;
-
- logRequest('Admin hard delete contact endpoint accessed', req, res, { contactId, adminUserId });
-
- const result = await container.deleteContactCommandHandler.execute({
- id: contactId,
- hard: true
- });
-
- AdminAuditService.logAdminAction('HARD_DELETE_CONTACT', adminUserId, {
- targetType: 'contact',
- targetId: contactId,
- operation: 'delete',
- sensitive: true
- }, req, res);
-
- logAuth('Contact hard deleted by admin', contactId, { adminUserId }, req, res);
- res.json({ success: result });
- } catch (error) {
- logError('Admin hard delete contact endpoint error', error as Error, req, res);
-
- if (error instanceof Error && error.message.includes('not found')) {
- return res.status(404).json({ error: 'Contact not found' });
- }
-
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-// =============================================================================
-// DECK IMPORT/EXPORT ROUTES (ADMIN)
-// =============================================================================
-
-// Import deck from JSON file (unencrypted, admin only)
-router.post('/decks/import', adminRequired, upload.single('file'), async (req: Request, res: Response) => {
- try {
- if (!req.file) {
- return res.status(400).json({ error: 'No file uploaded' });
- }
-
- const userId = (req as any).user.userId;
- const fileContent = req.file!.buffer.toString('utf-8');
-
- logRequest('Admin deck import from JSON endpoint accessed', req, res, { fileName: req.file.originalname });
-
- let jsonData;
- try {
- jsonData = JSON.parse(fileContent);
- } catch (parseError) {
- return res.status(400).json({ error: 'Invalid JSON format' });
- }
-
- // For admin import, we need to specify both target user and admin user
- // Let's assume the deck will be owned by the admin user doing the import
- const result = await container.deckImportExportService.adminImportFromJson(jsonData, userId, userId);
-
- logRequest('Admin deck import successful', req, res, { deckId: result.id, fileName: req.file.originalname });
-
- res.json({
- success: true,
- message: 'Deck imported successfully',
- deckId: result.id
- });
- } catch (error) {
- logError('Admin deck import from JSON error', error as Error, req, res);
- if (error instanceof Error && error.message.includes('Invalid')) {
- res.status(400).json({ error: 'Invalid deck data structure' });
- } else {
- res.status(500).json({ error: 'Internal server error' });
- }
- }
-});
-
-// Export deck as JSON (unencrypted, admin only)
-router.get('/decks/:deckId/export', adminRequired, async (req: Request, res: Response) => {
- try {
- const { deckId } = req.params;
-
- logRequest('Admin deck export as JSON endpoint accessed', req, res, { deckId });
-
- const deck = await container.deckRepository.findById(deckId);
- if (!deck) {
- logWarning('Deck not found for export', { deckId }, req, res);
- return res.status(404).json({ error: 'Deck not found' });
- }
-
- logRequest('Admin deck export successful', req, res, { deckId, deckName: deck.name });
-
- // Return deck as JSON for admin export
- res.setHeader('Content-Type', 'application/json');
- res.setHeader('Content-Disposition', `attachment; filename="${deck.name || 'deck'}.json"`);
- res.json(deck);
- } catch (error) {
- logError('Admin deck export as JSON error', error as Error, req, res);
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-export default router;
diff --git a/SerpentRace_Backend/src/Api/routers/chatRouter.ts b/SerpentRace_Backend/src/Api/routers/chatRouter.ts
deleted file mode 100644
index 140d6791..00000000
--- a/SerpentRace_Backend/src/Api/routers/chatRouter.ts
+++ /dev/null
@@ -1,287 +0,0 @@
-import express from 'express';
-import { authRequired } from '../../Application/Services/AuthMiddleware';
-import { container } from '../../Application/Services/DIContainer';
-import { ErrorResponseService } from '../../Application/Services/ErrorResponseService';
-import { ValidationMiddleware } from '../../Application/Services/ValidationMiddleware';
-import { logAuth, logError, logRequest, logWarning } from '../../Application/Services/Logger';
-
-const chatRouter = express.Router();
-
-// Get user's chats
-chatRouter.get('/user-chats', authRequired, async (req, res) => {
- try {
- const userId = (req as any).user.userId;
- const includeArchived = req.query.includeArchived === 'true';
-
- logRequest('Get user chats endpoint accessed', req, res, { userId, includeArchived });
-
- const chats = await container.getUserChatsQueryHandler.execute({
- userId,
- includeArchived
- });
-
- logRequest('User chats retrieved successfully', req, res, {
- userId,
- chatCount: chats.length
- });
-
- res.json(chats);
- } catch (error) {
- logError('Get user chats endpoint error', error as Error, req, res);
- return ErrorResponseService.sendInternalServerError(res);
- }
-});
-
-// Get chat history
-chatRouter.get('/history/:chatId',
- authRequired,
- ValidationMiddleware.validateUUIDFormat(['chatId']),
- async (req, res) => {
- try {
- const userId = (req as any).user.userId;
- const chatId = req.params.chatId;
-
- logRequest('Get chat history endpoint accessed', req, res, { userId, chatId });
-
- const history = await container.getChatHistoryQueryHandler.execute({
- chatId,
- userId
- });
-
- if (!history) {
- logWarning('Chat history not found or unauthorized', { userId, chatId }, req, res);
- return ErrorResponseService.sendNotFound(res, 'Chat not found or unauthorized');
- }
-
- logRequest('Chat history retrieved successfully', req, res, {
- userId,
- chatId,
- messageCount: history.messages.length,
- isArchived: history.isArchived
- });
-
- res.json(history);
- } catch (error) {
- logError('Get chat history endpoint error', error as Error, req, res);
- return ErrorResponseService.sendInternalServerError(res);
- }
-});
-
-// Create new chat (direct/group)
-chatRouter.post('/create',
- authRequired,
- ValidationMiddleware.combine([
- ValidationMiddleware.validateRequiredFields(['type', 'userIds']),
- ValidationMiddleware.validateAllowedValues({ type: ['direct', 'group'] }),
- ValidationMiddleware.validateNonEmptyArrays(['userIds'])
- ]),
- async (req, res) => {
- try {
- const userId = (req as any).user.userId;
- const { type, name, userIds } = req.body;
-
- logRequest('Create chat endpoint accessed', req, res, {
- userId,
- type,
- targetUserCount: userIds?.length || 0
- });
-
- if (type === 'group' && !name?.trim()) {
- return ErrorResponseService.sendBadRequest(res, 'Group name is required');
- }
-
- const chat = await container.createChatCommandHandler.execute({
- type,
- name: name?.trim(),
- createdBy: userId,
- userIds
- });
-
- if (!chat) {
- return ErrorResponseService.sendBadRequest(res, 'Failed to create chat');
- }
-
- logRequest('Chat created successfully', req, res, {
- userId,
- chatId: chat.id,
- chatType: chat.type
- });
-
- res.json({
- id: chat.id,
- type: chat.type,
- name: chat.name,
- users: chat.users,
- messages: chat.messages
- });
- } catch (error) {
- logError('Create chat endpoint error', error as Error, req, res);
-
- if (error instanceof Error) {
- if (error.message.includes('Premium subscription required')) {
- return ErrorResponseService.sendForbidden(res, 'Premium subscription required to create groups');
- }
- if (error.message.includes('not found')) {
- return ErrorResponseService.sendNotFound(res, 'One or more users not found');
- }
- }
-
- return ErrorResponseService.sendInternalServerError(res);
- }
-});
-
-// Send message (REST endpoint - mainly for testing, real messaging is via WebSocket)
-chatRouter.post('/message',
- authRequired,
- ValidationMiddleware.combine([
- ValidationMiddleware.validateRequiredFields(['chatId', 'message']),
- ValidationMiddleware.validateUUIDFormat(['chatId']),
- ValidationMiddleware.validateStringLength({ message: { min: 1, max: 2000 } })
- ]),
- async (req, res) => {
- try {
- const userId = (req as any).user.userId;
- const { chatId, message } = req.body;
-
- logRequest('Send message endpoint accessed', req, res, {
- userId,
- chatId,
- messageLength: message?.length || 0
- });
-
- const sentMessage = await container.sendMessageCommandHandler.execute({
- chatId,
- userId,
- message
- });
-
- if (!sentMessage) {
- return ErrorResponseService.sendBadRequest(res, 'Failed to send message');
- }
-
- logRequest('Message sent successfully', req, res, {
- userId,
- chatId,
- messageId: sentMessage.id
- });
-
- res.json(sentMessage);
- } catch (error) {
- logError('Send message endpoint error', error as Error, req, res);
-
- if (error instanceof Error) {
- if (error.message.includes('Chat not found')) {
- return ErrorResponseService.sendNotFound(res, 'Chat not found');
- }
- if (error.message.includes('not a member')) {
- return ErrorResponseService.sendForbidden(res, 'Not authorized to send messages to this chat');
- }
- if (error.message.includes('non-empty string')) {
- return ErrorResponseService.sendBadRequest(res, 'Message must be a non-empty string');
- }
- }
-
- return ErrorResponseService.sendInternalServerError(res);
- }
-});
-
-// Archive chat manually
-chatRouter.post('/archive/:chatId',
- authRequired,
- ValidationMiddleware.validateUUIDFormat(['chatId']),
- async (req, res) => {
- try {
- const userId = (req as any).user.userId;
- const chatId = req.params.chatId;
-
- logRequest('Archive chat endpoint accessed', req, res, { userId, chatId });
-
- // Check if user has access to this chat
- const chat = await container.chatRepository.findById(chatId);
- if (!chat) {
- return ErrorResponseService.sendNotFound(res, 'Chat not found');
- }
-
- if (!chat.users.includes(userId)) {
- return ErrorResponseService.sendForbidden(res, 'Not authorized to archive this chat');
- }
-
- const success = await container.archiveChatCommandHandler.execute({ chatId });
-
- if (!success) {
- return ErrorResponseService.sendBadRequest(res, 'Failed to archive chat');
- }
-
- logRequest('Chat archived successfully', req, res, { userId, chatId });
- res.json({ success: true, message: 'Chat archived successfully' });
-
- } catch (error) {
- logError('Archive chat endpoint error', error as Error, req, res);
- return ErrorResponseService.sendInternalServerError(res);
- }
-});
-
-// Restore chat from archive
-chatRouter.post('/restore/:chatId',
- authRequired,
- ValidationMiddleware.validateUUIDFormat(['chatId']),
- async (req, res) => {
- try {
- const userId = (req as any).user.userId;
- const chatId = req.params.chatId;
-
- logRequest('Restore chat endpoint accessed', req, res, { userId, chatId });
-
- // Check if user has access to this archived chat
- const archive = await container.chatArchiveRepository.findByChatId(chatId);
- const userArchive = archive.find((a: any) => a.participants.includes(userId));
-
- if (!userArchive) {
- return ErrorResponseService.sendNotFound(res, 'Archived chat not found or unauthorized');
- }
-
- const success = await container.restoreChatCommandHandler.execute({ chatId });
-
- if (!success) {
- return ErrorResponseService.sendBadRequest(res, 'Failed to restore chat (game chats cannot be restored)');
- }
-
- logRequest('Chat restored successfully', req, res, { userId, chatId });
- res.json({ success: true, message: 'Chat restored successfully' });
-
- } catch (error) {
- logError('Restore chat endpoint error', error as Error, req, res);
- return ErrorResponseService.sendInternalServerError(res);
- }
-});
-
-// Get archived chats for a game
-chatRouter.get('/archived/game/:gameId',
- authRequired,
- ValidationMiddleware.validateUUIDFormat(['gameId']),
- async (req, res) => {
- try {
- const userId = (req as any).user.userId;
- const gameId = req.params.gameId;
-
- logRequest('Get archived game chats endpoint accessed', req, res, { userId, gameId });
-
- const archivedChats = await container.getArchivedChatsQueryHandler.execute({
- userId,
- gameId
- });
-
- logRequest('Archived game chats retrieved successfully', req, res, {
- userId,
- gameId,
- chatCount: archivedChats.length
- });
-
- res.json(archivedChats);
- } catch (error) {
- logError('Get archived game chats endpoint error', error as Error, req, res);
- return ErrorResponseService.sendInternalServerError(res);
- }
-});
-
-export default chatRouter;
diff --git a/SerpentRace_Backend/src/Api/routers/contactRouter.ts b/SerpentRace_Backend/src/Api/routers/contactRouter.ts
deleted file mode 100644
index d7fcbb53..00000000
--- a/SerpentRace_Backend/src/Api/routers/contactRouter.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-import { Router } from 'express';
-import { container } from '../../Application/Services/DIContainer';
-import { logRequest, logError } from '../../Application/Services/Logger';
-import { ContactType } from '../../Domain/Contact/ContactAggregate';
-
-const contactRouter = Router();
-
-// Public endpoint - anyone can create a contact
-contactRouter.post('/', async (req, res) => {
- try {
- // Get user ID if authenticated (optional)
- const userId = (req as any).user?.userId || null;
-
- const { name, email, type, txt } = req.body;
-
- // Validate required fields
- if (!name || !email || type === undefined || !txt) {
- return res.status(400).json({
- error: 'Missing required fields: name, email, type, and txt are required'
- });
- }
-
- // Validate type
- if (!Object.values(ContactType).includes(Number(type))) {
- return res.status(400).json({
- error: 'Invalid contact type. Must be one of: 0 (Bug), 1 (Problem), 2 (Question), 3 (Sales), 4 (Other)'
- });
- }
-
- logRequest('Create contact endpoint accessed', req, res, { name, email, type, userId });
-
- const result = await container.createContactCommandHandler.execute({
- name,
- email,
- userid: userId,
- type: Number(type),
- txt
- });
-
- logRequest('Contact created successfully', req, res, { contactId: result.id, name, email, type });
- res.status(201).json(result);
- } catch (error) {
- logError('Create contact endpoint error', error as Error, req, res);
-
- if (error instanceof Error && error.message.includes('validation')) {
- return res.status(400).json({ error: 'Invalid input data', details: error.message });
- }
-
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-export default contactRouter;
diff --git a/SerpentRace_Backend/src/Api/routers/deckImportExportRouter.ts b/SerpentRace_Backend/src/Api/routers/deckImportExportRouter.ts
deleted file mode 100644
index cf205d6d..00000000
--- a/SerpentRace_Backend/src/Api/routers/deckImportExportRouter.ts
+++ /dev/null
@@ -1,124 +0,0 @@
-import express, { Request, Response } from 'express';
-import multer from 'multer';
-import { DIContainer } from '../../Application/Services/DIContainer';
-import { authRequired } from '../../Application/Services/AuthMiddleware';
-import { logRequest, logError, logWarning } from '../../Application/Services/Logger';
-
-// Extend Express Request interface for file uploads
-declare global {
- namespace Express {
- interface Request {
- file?: Express.Multer.File;
- }
- }
-}
-
-const router = express.Router();
-const container = DIContainer.getInstance();
-
-// Configure multer for file uploads
-const upload = multer({
- storage: multer.memoryStorage(),
- limits: {
- fileSize: 10 * 1024 * 1024, // 10MB limit
- },
- fileFilter: (req: any, file: any, cb: any) => {
- if (file.mimetype === 'application/json' || file.originalname.endsWith('.spr')) {
- cb(null, true);
- } else {
- cb(new Error('Only JSON and .spr files are allowed'));
- }
- }
-});
-
-// Export deck to .spr file (encrypted) - users can only export their own decks
-router.get('/export/:deckId', authRequired, async (req: Request, res: Response) => {
- try {
- const { deckId } = req.params;
- const userId = (req as any).user.userId;
-
- logRequest('Export deck endpoint accessed', req, res, { deckId, userId });
-
- // Check if user owns the deck
- const deck = await container.deckRepository.findById(deckId);
- if (!deck) {
- logWarning('Deck not found for export', { deckId, userId }, req, res);
- return res.status(404).json({ error: 'Deck not found' });
- }
-
- // Users can only export their own decks
- if (deck.userid !== userId) {
- logWarning('Access denied - user attempted to export deck they do not own', {
- deckId,
- userId,
- deckOwnerId: deck.userid
- }, req, res);
- return res.status(403).json({ error: 'Access denied - you can only export your own decks' });
- }
-
- const sprData = await container.deckImportExportService.exportDeckToSpr(deckId, userId);
-
- res.setHeader('Content-Type', 'application/octet-stream');
- res.setHeader('Content-Disposition', `attachment; filename="${deck.name || 'deck'}.spr"`);
-
- logRequest('Deck exported successfully', req, res, {
- deckId,
- userId,
- deckName: deck.name,
- fileSize: sprData.length
- });
-
- res.send(sprData);
- } catch (error) {
- logError('Export deck endpoint error', error as Error, req, res);
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-// Import deck from .spr file (encrypted) - imported deck will be owned by the importing user
-router.post('/import', authRequired, upload.single('file'), async (req: Request, res: Response) => {
- try {
- const userId = (req as any).user.userId;
-
- logRequest('Import deck endpoint accessed', req, res, {
- userId,
- hasFile: !!req.file,
- fileName: req.file?.originalname,
- fileSize: req.file?.size
- });
-
- if (!req.file) {
- logWarning('No file uploaded for deck import', { userId }, req, res);
- return res.status(400).json({ error: 'No file uploaded' });
- }
-
- const fileBuffer = req.file!.buffer;
-
- // Import the deck and assign ownership to the current user
- const result = await container.deckImportExportService.importDeckFromSpr(fileBuffer, userId);
-
- logRequest('Deck imported successfully', req, res, {
- userId,
- deckId: result.id,
- deckName: result.name || 'Unknown',
- fileName: req.file.originalname,
- fileSize: req.file.size
- });
-
- res.json({
- success: true,
- message: 'Deck imported successfully and added to your collection',
- deckId: result.id
- });
- } catch (error) {
- logError('Import deck endpoint error', error as Error, req, res);
-
- if (error instanceof Error && error.message.includes('Invalid')) {
- return res.status(400).json({ error: 'Invalid file format or corrupted data' });
- } else {
- res.status(500).json({ error: 'Internal server error' });
- }
- }
-});
-
-export default router;
diff --git a/SerpentRace_Backend/src/Api/routers/deckRouter.ts b/SerpentRace_Backend/src/Api/routers/deckRouter.ts
deleted file mode 100644
index 67632a33..00000000
--- a/SerpentRace_Backend/src/Api/routers/deckRouter.ts
+++ /dev/null
@@ -1,266 +0,0 @@
-import { Router } from 'express';
-import { authRequired } from '../../Application/Services/AuthMiddleware';
-import { container } from '../../Application/Services/DIContainer';
-import { ErrorResponseService } from '../../Application/Services/ErrorResponseService';
-import { ValidationMiddleware } from '../../Application/Services/ValidationMiddleware';
-import { GeneralSearchService } from '../../Application/Search/Generalsearch';
-import { logRequest, logError, logWarning } from '../../Application/Services/Logger';
-import { Type, CType } from '../../Domain/Deck/DeckAggregate';
-
-const deckRouter = Router();
-
-/**
- * Helper function to convert string enum values to integer enum values
- */
-function convertEnumValues(data: any): any {
- const converted = { ...data };
-
- // Convert Type enum
- if (converted.type && typeof converted.type === 'string') {
- switch (converted.type.toUpperCase()) {
- case 'LUCK':
- converted.type = Type.LUCK;
- break;
- case 'JOKER':
- converted.type = Type.JOKER;
- break;
- case 'QUESTION':
- converted.type = Type.QUESTION;
- break;
- default:
- throw new Error('Invalid deck type. Must be LUCK, JOKER, or QUESTION');
- }
- }
-
- // Convert CType enum
- if (converted.ctype && typeof converted.ctype === 'string') {
- switch (converted.ctype.toUpperCase()) {
- case 'PUBLIC':
- converted.ctype = CType.PUBLIC;
- break;
- case 'PRIVATE':
- converted.ctype = CType.PRIVATE;
- break;
- case 'ORGANIZATION':
- converted.ctype = CType.ORGANIZATION;
- break;
- default:
- throw new Error('Invalid deck ctype. Must be PUBLIC, PRIVATE, or ORGANIZATION');
- }
- }
-
- return converted;
-}
-
-// Create search service that isn't in the container yet
-const searchService = new GeneralSearchService(container.userRepository, container.organizationRepository, container.deckRepository);
-
-// Authenticated routes - Get decks with pagination (RECOMMENDED)
-deckRouter.get('/page/:from/:to', authRequired, async (req, res) => {
- try {
- const userId = (req as any).user.userId;
- const userOrgId = (req as any).user.orgId;
- const isAdmin = (req as any).user.authLevel === 1;
- const from = parseInt(req.params.from);
- const to = parseInt(req.params.to);
-
- if (isNaN(from) || isNaN(to) || from < 0 || to < from) {
- return res.status(400).json({ error: 'Invalid page parameters. "from" and "to" must be valid numbers with to >= from >= 0' });
- }
-
- logRequest('Get decks by page endpoint accessed', req, res, {
- userId,
- userOrgId,
- isAdmin,
- from,
- to
- });
-
- // Use paginated query handler for memory efficiency
- const result = await container.getDecksByPageQueryHandler.execute({
- userId,
- userOrgId,
- isAdmin,
- from,
- to
- });
-
- logRequest('Get decks page completed successfully', req, res, {
- userId,
- from,
- to,
- returnedCount: result.decks.length,
- totalCount: result.totalCount
- });
-
- res.json(result);
- } catch (error) {
- logError('Get decks by page endpoint error', error as Error, req, res);
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-deckRouter.post('/', authRequired, async (req, res) => {
- try {
- const userId = (req as any).user.userId;
- logRequest('Create deck endpoint accessed', req, res, { name: req.body.name, userId });
-
- // Convert string enum values to integers
- const command = convertEnumValues({
- ...req.body,
- userid: userId
- });
-
- const result = await container.createDeckCommandHandler.execute(command);
-
- logRequest('Deck created successfully', req, res, { deckId: result.id, name: req.body.name, userId });
- res.json(result);
- } catch (error) {
- logError('Create deck endpoint error', error as Error, req, res);
-
- // Handle enum validation errors
- if (error instanceof Error && error.message.includes('Invalid deck')) {
- return res.status(400).json({ error: error.message });
- }
-
- if (error instanceof Error && (error.message.includes('duplicate') || error.message.includes('unique constraint'))) {
- return res.status(409).json({ error: 'Deck with this name already exists' });
- }
-
- if (error instanceof Error && error.message.includes('validation')) {
- return res.status(400).json({ error: 'Invalid input data', details: error.message });
- }
-
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-deckRouter.get('/search', authRequired, async (req, res) => {
- try {
- const { query, limit, offset } = req.query;
- logRequest('Search decks endpoint accessed', req, res, { query, limit, offset });
-
- if (!query || typeof query !== 'string') {
- logWarning('Deck search attempted without query', { query, hasQuery: !!query }, req, res);
- return res.status(400).json({ error: 'Search query is required' });
- }
-
- const searchQuery = {
- query: query.trim(),
- limit: limit ? parseInt(limit as string) : 20,
- offset: offset ? parseInt(offset as string) : 0
- };
-
- // Validate pagination parameters
- if (searchQuery.limit < 1 || searchQuery.limit > 100) {
- logWarning('Invalid deck search limit parameter', { limit: searchQuery.limit }, req, res);
- return res.status(400).json({ error: 'Limit must be between 1 and 100' });
- }
-
- if (searchQuery.offset < 0) {
- logWarning('Invalid deck search offset parameter', { offset: searchQuery.offset }, req, res);
- return res.status(400).json({ error: 'Offset must be non-negative' });
- }
-
- const result = await searchService.searchFromUrl(req.originalUrl, searchQuery);
-
- logRequest('Deck search completed successfully', req, res, {
- query: searchQuery.query,
- resultCount: Array.isArray(result) ? result.length : 0
- });
- res.json(result);
- } catch (error) {
- logError('Search decks endpoint error', error as Error, req, res);
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-deckRouter.get('/:id', authRequired, async (req, res) => {
- try {
- const deckId = req.params.id;
- logRequest('Get deck by id endpoint accessed', req, res, { deckId });
-
- const result = await container.getDeckByIdQueryHandler.execute({ id: deckId });
-
- if (!result) {
- logWarning('Deck not found', { deckId }, req, res);
- return res.status(404).json({ error: 'Deck not found' });
- }
-
- logRequest('Deck retrieved successfully', req, res, { deckId });
- res.json(result);
- } catch (error) {
- logError('Get deck by id endpoint error', error as Error, req, res);
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-deckRouter.patch('/:id', authRequired, async (req, res) => {
- try {
- const deckId = req.params.id;
- const userId = (req as any).user.userId;
- const authLevel = (req as any).user.authLevel;
- logRequest('Update deck endpoint accessed', req, res, { deckId, userId, updateFields: Object.keys(req.body) });
-
- // Convert string enum values to integers
- const updateData = convertEnumValues(req.body);
-
- const result = await container.updateDeckCommandHandler.execute({ userid: userId, authLevel: authLevel, id: deckId, ...updateData });
-
- logRequest('Deck updated successfully', req, res, { deckId, userId });
- res.json(result);
- } catch (error) {
- logError('Update deck endpoint error', error as Error, req, res);
-
- // Handle enum validation errors
- if (error instanceof Error && error.message.includes('Invalid deck')) {
- return res.status(400).json({ error: error.message });
- }
-
- if (error instanceof Error && error.message.includes('not found')) {
- return res.status(404).json({ error: 'Deck not found' });
- }
-
- if (error instanceof Error && (error.message.includes('duplicate') || error.message.includes('unique constraint'))) {
- return res.status(409).json({ error: 'Deck with this name already exists' });
- }
-
- if (error instanceof Error && error.message.includes('validation')) {
- return res.status(400).json({ error: 'Invalid input data', details: error.message });
- }
-
- if (error instanceof Error && error.message.includes('admin')) {
- return res.status(403).json({ error: 'Forbidden: ' + error.message });
- }
-
- if (error instanceof Error && error.message.includes('admin')) {
- return res.status(403).json({ error: 'Forbidden: ' + error.message });
- }
-
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-deckRouter.delete('/:id', authRequired, async (req, res) => {
- try {
- const deckId = req.params.id;
- const userId = (req as any).user.userId;
- const authLevel = (req as any).user.authLevel;
- logRequest('Soft delete deck endpoint accessed', req, res, { deckId, userId });
-
- const result = await container.deleteDeckCommandHandler.execute({ userid: userId, authLevel: authLevel, id: deckId, soft: true });
-
- logRequest('Deck soft delete successful', req, res, { deckId, userId, success: result });
- res.json({ success: result });
- } catch (error) {
- logError('Soft delete deck endpoint error', error as Error, req, res);
-
- if (error instanceof Error && error.message.includes('not found')) {
- return res.status(404).json({ error: 'Deck not found' });
- }
-
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-export default deckRouter;
\ No newline at end of file
diff --git a/SerpentRace_Backend/src/Api/routers/gameRouter.ts b/SerpentRace_Backend/src/Api/routers/gameRouter.ts
deleted file mode 100644
index 982cf163..00000000
--- a/SerpentRace_Backend/src/Api/routers/gameRouter.ts
+++ /dev/null
@@ -1,327 +0,0 @@
-import { Router } from 'express';
-import { authRequired } from '../../Application/Services/AuthMiddleware';
-import { optionalAuth } from '../middleware/optionalAuth';
-import { container } from '../../Application/Services/DIContainer';
-import { ErrorResponseService } from '../../Application/Services/ErrorResponseService';
-import { ValidationMiddleware } from '../../Application/Services/ValidationMiddleware';
-import { logRequest, logError, logWarning } from '../../Application/Services/Logger';
-import { LoginType } from '../../Domain/Game/GameAggregate';
-
-const gameRouter = Router();
-
-gameRouter.post('/start', authRequired, async (req, res) => {
- try {
- const userId = (req as any).user.userId;
- const orgId = (req as any).user.orgId;
- const { deckids, maxplayers, logintype } = req.body;
-
- logRequest('Start game endpoint accessed', req, res, {
- userId,
- orgId,
- deckCount: deckids?.length,
- maxplayers,
- logintype
- });
-
- // Validate required fields
- if (!deckids || !Array.isArray(deckids) || deckids.length === 0) {
- return res.status(400).json({ error: 'deckids is required and must be a non-empty array' });
- }
-
- if (!maxplayers || typeof maxplayers !== 'number') {
- return res.status(400).json({ error: 'maxplayers is required and must be a number' });
- }
-
- if (logintype === undefined || typeof logintype !== 'number') {
- return res.status(400).json({ error: 'logintype is required and must be a number (0=PUBLIC, 1=PRIVATE, 2=ORGANIZATION)' });
- }
-
- // Start the game using the GameService
- const game = await container.gameService.startGame(
- deckids,
- maxplayers,
- logintype as LoginType,
- userId,
- orgId
- );
-
- logRequest('Game started successfully', req, res, {
- userId,
- gameId: game.id,
- gameCode: game.gamecode,
- deckCount: game.gamedecks.length,
- totalCards: game.gamedecks.reduce((sum, deck) => sum + deck.cards.length, 0)
- });
-
- res.json(game);
- } catch (error) {
- logError('Start game endpoint error', error as Error, req, res);
-
- if (error instanceof Error) {
- if (error.message.includes('not found')) {
- return res.status(404).json({ error: error.message });
- }
- if (error.message.includes('validation') ||
- error.message.includes('must be') ||
- error.message.includes('required') ||
- error.message.includes('Invalid')) {
- return res.status(400).json({ error: error.message });
- }
- }
-
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-gameRouter.post('/join', optionalAuth, async (req, res) => {
- try {
- const user = (req as any).user;
- const { gameCode, playerName } = req.body;
-
- logRequest('Join game endpoint accessed', req, res, {
- gameCode,
- playerName,
- hasAuth: !!user,
- userId: user?.userId,
- orgId: user?.orgId
- });
-
- // Validate required fields
- if (!gameCode || typeof gameCode !== 'string') {
- return res.status(400).json({ error: 'gameCode is required and must be a string' });
- }
-
- if (gameCode.length !== 6) {
- return res.status(400).json({ error: 'gameCode must be exactly 6 characters long' });
- }
-
- // First, we need to find the game to determine its type
- const gameRepository = container.gameRepository;
- const gameToJoin = await gameRepository.findByGameCode(gameCode);
-
- if (!gameToJoin) {
- return res.status(404).json({ error: 'Game not found' });
- }
-
- // Determine join requirements based on game login type
- let actualPlayerId: string | undefined;
- let actualPlayerName: string | undefined;
- let actualOrgId: string | null = null;
-
- switch (gameToJoin.logintype) {
- case LoginType.PUBLIC:
- // Public games: playerName required, authentication optional
- // If user is logged in and no playerName provided, use their username
- if (!playerName || typeof playerName !== 'string' || !playerName.trim()) {
- if (user && user.userId) {
- // User is logged in, fetch their username to use as playerName
- try {
- const userDetails = await container.getUserByIdQueryHandler.execute({ id: user.userId });
- if (userDetails && userDetails.username) {
- actualPlayerName = userDetails.username;
- logRequest('Using logged-in user\'s username as playerName', req, res, {
- userId: user.userId,
- username: userDetails.username
- });
- } else {
- return res.status(400).json({
- error: 'playerName is required for public games'
- });
- }
- } catch (error) {
- logError('Failed to fetch user details for playerName', error as Error, req, res);
- return res.status(400).json({
- error: 'playerName is required for public games'
- });
- }
- } else {
- // User is not logged in, playerName is required
- return res.status(400).json({
- error: 'playerName is required for public games'
- });
- }
- } else {
- // playerName was provided, use it
- actualPlayerName = playerName.trim();
- }
- actualPlayerId = user?.userId; // Use authenticated user ID if available, otherwise undefined
- break;
-
- case LoginType.PRIVATE:
- // Private games: authentication required
- if (!user || !user.userId) {
- return res.status(401).json({
- error: 'Authentication required to join private games'
- });
- }
- actualPlayerId = user.userId;
- actualPlayerName = playerName;
- break;
-
- case LoginType.ORGANIZATION:
- // Organization games: authentication + organization membership required
- if (!user || !user.userId) {
- return res.status(401).json({
- error: 'Authentication required to join organization games'
- });
- }
-
- if (!user.orgId) {
- return res.status(403).json({
- error: 'Organization membership required to join organization games'
- });
- }
-
- if (gameToJoin.orgid && user.orgId !== gameToJoin.orgid) {
- return res.status(403).json({
- error: 'You must be a member of the same organization to join this game'
- });
- }
-
- actualPlayerId = user.userId;
- actualPlayerName = playerName;
- actualOrgId = user.orgId;
- break;
-
- default:
- return res.status(400).json({ error: 'Invalid game type' });
- }
-
- // Join the game using the GameService with determined parameters
- const game = await container.gameService.joinGame(
- gameCode,
- actualPlayerId,
- actualPlayerName,
- actualOrgId,
- gameToJoin.logintype
- );
-
- logRequest('Player joined game successfully', req, res, {
- userId: actualPlayerId || 'anonymous',
- gameId: game.id,
- gameCode: game.gamecode,
- gameType: LoginType[gameToJoin.logintype],
- playerCount: game.players.length,
- maxPlayers: game.maxplayers,
- playerName: actualPlayerName
- });
-
- // Create game token for WebSocket authentication
- const gameTokenService = container.gameTokenService;
- const gameToken = gameTokenService.createGameToken(
- game.id,
- game.gamecode,
- actualPlayerName || 'Anonymous',
- actualPlayerId
- );
-
- // Return clean response with essential data + game token
- res.json({
- id: game.id,
- gamecode: game.gamecode,
- playerName: actualPlayerName,
- playerCount: game.players.length,
- maxPlayers: game.maxplayers,
- gameType: LoginType[gameToJoin.logintype],
- isAuthenticated: !!actualPlayerId,
- gameToken: gameToken
- });
- } catch (error) {
- logError('Join game endpoint error', error as Error, req, res);
-
- if (error instanceof Error) {
- if (error.message.includes('not found')) {
- return res.status(404).json({ error: error.message });
- }
- if (error.message.includes('Authentication required')) {
- return res.status(401).json({ error: error.message });
- }
- if (error.message.includes('Organization') || error.message.includes('organization')) {
- return res.status(403).json({ error: error.message });
- }
- if (error.message.includes('full') ||
- error.message.includes('already in') ||
- error.message.includes('not accepting')) {
- return res.status(409).json({ error: error.message });
- }
- if (error.message.includes('validation') ||
- error.message.includes('must be') ||
- error.message.includes('required') ||
- error.message.includes('Invalid')) {
- return res.status(400).json({ error: error.message });
- }
- }
-
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-gameRouter.post('/:gameId/start', authRequired, async (req, res) => {
- try {
- const userId = (req as any).user.userId;
- const { gameId } = req.params;
-
- logRequest('Start gameplay endpoint accessed', req, res, {
- userId,
- gameId
- });
-
- // Validate required fields
- if (!gameId || typeof gameId !== 'string') {
- return res.status(400).json({ error: 'gameId is required and must be a string' });
- }
-
- // Start the gameplay using the GameService
- const result = await container.gameService.startGamePlay(gameId, userId);
-
- logRequest('Game gameplay started successfully', req, res, {
- userId,
- gameId,
- playerCount: result.game.players.length
- });
-
- res.json({
- message: 'Game started successfully',
- gameId: gameId,
- playerCount: result.game.players.length,
- game: result.game,
- boardData: result.boardData
- });
- } catch (error) {
- logError('Start gameplay endpoint error', error as Error, req, res);
-
- if (error instanceof Error) {
- if (error.message.includes('not found')) {
- return res.status(404).json({ error: error.message });
- }
- if (error.message.includes('Only') || error.message.includes('master')) {
- return res.status(403).json({ error: error.message });
- }
- if (error.message.includes('already started') ||
- error.message.includes('not ready') ||
- error.message.includes('minimum players') ||
- error.message.includes('not in waiting state') ||
- error.message.includes('cannot be started')) {
- return res.status(409).json({ error: error.message });
- }
- if (error.message.includes('validation') ||
- error.message.includes('must be') ||
- error.message.includes('required') ||
- error.message.includes('Invalid')) {
- return res.status(400).json({ error: error.message });
- }
- // Board generation specific errors
- if (error.message.includes('Board generation') ||
- error.message.includes('board not found') ||
- error.message.includes('BoardGenerationService') ||
- error.message.includes('Failed to wait for board generation') ||
- error.message.includes('board generation timeout')) {
- return res.status(500).json({ error: error.message });
- }
- }
-
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-export default gameRouter;
\ No newline at end of file
diff --git a/SerpentRace_Backend/src/Api/routers/organizationRouter.ts b/SerpentRace_Backend/src/Api/routers/organizationRouter.ts
deleted file mode 100644
index eceaad01..00000000
--- a/SerpentRace_Backend/src/Api/routers/organizationRouter.ts
+++ /dev/null
@@ -1,204 +0,0 @@
-import { Router } from 'express';
-import { authRequired } from '../../Application/Services/AuthMiddleware';
-import { container } from '../../Application/Services/DIContainer';
-import { ErrorResponseService } from '../../Application/Services/ErrorResponseService';
-import { ValidationMiddleware } from '../../Application/Services/ValidationMiddleware';
-import { GeneralSearchService } from '../../Application/Search/Generalsearch';
-import { logRequest, logError, logWarning, logAuth } from '../../Application/Services/Logger';
-
-const organizationRouter = Router();
-
-// Create search service that isn't in the container yet
-const searchService = new GeneralSearchService(container.userRepository, container.organizationRepository, container.deckRepository);
-
-// Auth routes - Get organizations with pagination (RECOMMENDED)
-organizationRouter.get('/page/:from/:to', authRequired, async (req, res) => {
- try {
- const from = parseInt(req.params.from);
- const to = parseInt(req.params.to);
-
- if (isNaN(from) || isNaN(to) || from < 0 || to < from) {
- return res.status(400).json({ error: 'Invalid page parameters. "from" and "to" must be valid numbers with to >= from >= 0' });
- }
-
- logRequest('Get organizations by page endpoint accessed', req, res, { from, to });
-
- const result = await container.getOrganizationsByPageQueryHandler.execute({ from, to });
-
- logRequest('Organizations page retrieved successfully', req, res, {
- from,
- to,
- count: result.organizations.length,
- totalCount: result.totalCount
- });
-
- res.json(result);
- } catch (error) {
- logError('Get organizations by page endpoint error', error as Error, req, res);
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-organizationRouter.get('/search', authRequired, async (req, res) => {
- try {
- const { query, limit, offset } = req.query;
- logRequest('Search organizations endpoint accessed', req, res, { query, limit, offset });
-
- if (!query || typeof query !== 'string') {
- logWarning('Organization search attempted without query', { query, hasQuery: !!query }, req, res);
- return res.status(400).json({ error: 'Search query is required' });
- }
-
- const searchQuery = {
- query: query.trim(),
- limit: limit ? parseInt(limit as string) : 20,
- offset: offset ? parseInt(offset as string) : 0
- };
-
- // Validate pagination parameters
- if (searchQuery.limit < 1 || searchQuery.limit > 100) {
- logWarning('Invalid organization search limit parameter', { limit: searchQuery.limit }, req, res);
- return res.status(400).json({ error: 'Limit must be between 1 and 100' });
- }
-
- if (searchQuery.offset < 0) {
- logWarning('Invalid organization search offset parameter', { offset: searchQuery.offset }, req, res);
- return res.status(400).json({ error: 'Offset must be non-negative' });
- }
-
- const result = await searchService.searchFromUrl(req.originalUrl, searchQuery);
-
- logRequest('Organization search completed successfully', req, res, {
- query: searchQuery.query,
- resultCount: Array.isArray(result) ? result.length : 0
- });
- res.json(result);
- } catch (error) {
- logError('Search organizations endpoint error', error as Error, req, res);
- res.status(500).json({ error: 'Internal server error' });
- }
-});
-
-// Get organization login URL
-organizationRouter.get('/:orgId/login-url', authRequired, async (req, res) => {
- try {
- const userId = (req as any).user.userId;
- const { orgId } = req.params;
-
- logRequest('Get organization login URL endpoint accessed', req, res, {
- userId,
- organizationId: orgId
- });
-
- const result = await container.getOrganizationLoginUrlQueryHandler.execute({
- organizationId: orgId
- });
-
- if (!result) {
- logWarning('Organization login URL not found', {
- organizationId: orgId,
- userId
- }, req, res);
- return ErrorResponseService.sendNotFound(res, 'Organization login URL not found');
- }
-
- logRequest('Organization login URL retrieved successfully', req, res, {
- organizationId: orgId,
- organizationName: result.organizationName,
- hasUrl: !!result.loginUrl,
- userId
- });
-
- res.json(result);
- } catch (error) {
- logError('Get organization login URL endpoint error', error as Error, req, res);
- return ErrorResponseService.sendInternalServerError(res);
- }
-});
-
-// Process third-party authentication callback
-organizationRouter.post('/auth-callback', authRequired, async (req, res) => {
- try {
- const userId = (req as any).user.userId;
- const { organizationId, status, authToken } = req.body;
-
- logRequest('Organization auth callback endpoint accessed', req, res, {
- userId,
- organizationId,
- status,
- hasAuthToken: !!authToken
- });
-
- // Validate required fields
- if (!organizationId || !status) {
- logWarning('Missing required fields for organization auth callback', {
- organizationId: !!organizationId,
- status: !!status,
- userId
- }, req, res);
- return ErrorResponseService.sendBadRequest(res, 'organizationId and status are required');
- }
-
- if (status !== 'ok' && status !== 'not_ok') {
- logWarning('Invalid status value for organization auth callback', {
- status,
- userId,
- organizationId
- }, req, res);
- return ErrorResponseService.sendBadRequest(res, 'status must be either "ok" or "not_ok"');
- }
-
- const result = await container.processOrgAuthCallbackCommandHandler.execute({
- organizationId,
- userId,
- status,
- authToken
- });
-
- if (!result.success) {
- if (result.message.includes('not found')) {
- logWarning('Organization auth callback failed - entity not found', {
- userId,
- organizationId,
- message: result.message
- }, req, res);
- return ErrorResponseService.sendNotFound(res, result.message);
- }
- if (result.message.includes('does not belong')) {
- logWarning('Organization auth callback failed - authorization error', {
- userId,
- organizationId,
- message: result.message
- }, req, res);
- return ErrorResponseService.sendForbidden(res, result.message);
- }
- if (result.message.includes('authentication failed')) {
- logAuth('Organization authentication failed via callback', userId, {
- organizationId,
- status
- }, req, res);
- return ErrorResponseService.sendUnauthorized(res, result.message);
- }
-
- logError('Organization auth callback internal error', new Error(result.message), req, res);
- return ErrorResponseService.sendInternalServerError(res);
- }
-
- logAuth('Organization auth callback processed successfully', userId, {
- organizationId,
- status,
- updatedFields: result.updatedFields
- }, req, res);
-
- res.json({
- success: result.success,
- message: result.message,
- updatedFields: result.updatedFields
- });
- } catch (error) {
- logError('Organization auth callback endpoint error', error as Error, req, res);
- return ErrorResponseService.sendInternalServerError(res);
- }
-});
-
-export default organizationRouter;
diff --git a/SerpentRace_Backend/src/Api/routers/userRouter.ts b/SerpentRace_Backend/src/Api/routers/userRouter.ts
deleted file mode 100644
index facc906d..00000000
--- a/SerpentRace_Backend/src/Api/routers/userRouter.ts
+++ /dev/null
@@ -1,345 +0,0 @@
-import { Router } from 'express';
-import { authRequired } from '../../Application/Services/AuthMiddleware';
-import { container } from '../../Application/Services/DIContainer';
-import { ErrorResponseService } from '../../Application/Services/ErrorResponseService';
-import { ValidationMiddleware } from '../../Application/Services/ValidationMiddleware';
-import { GeneralSearchService } from '../../Application/Search/Generalsearch';
-import { logRequest, logError, logAuth, logWarning } from '../../Application/Services/Logger';
-
-const userRouter = Router();
-
-// Create search service that isn't in the container yet
-const searchService = new GeneralSearchService(container.userRepository, container.organizationRepository, container.deckRepository);
-
-// Login endpoint
-userRouter.post('/login',
- ValidationMiddleware.combine([
- ValidationMiddleware.validateRequiredFields(['username', 'password']),
- ValidationMiddleware.validateStringLength({
- username: { min: 3, max: 50 },
- password: { min: 6, max: 100 }
- })
- ]),
- async (req, res) => {
- try {
- logRequest('Login endpoint accessed', req, res, { username: req.body.username });
-
- const { username, password } = req.body;
-
- const result = await container.loginCommandHandler.execute({ username, password }, res);
-
- if (result) {
- logAuth('User login successful', undefined, { username: result.user.username }, req, res);
- res.json(result);
- } else {
- throw new Error(`Login failed: ${result}`);
- }
-
- } catch (error) {
- logError('Login endpoint error', error as Error, req, res);
-
- if (error instanceof Error) {
- if (error.message.includes('Invalid username')) {
- return ErrorResponseService.sendUnauthorized(res, 'Invalid username or password');
- }
- if (error.message.includes('Invalid password')) {
- return ErrorResponseService.sendUnauthorized(res, 'Invalid username or password');
- }
- if (error.message.includes('not verified')) {
- return ErrorResponseService.sendUnauthorized(res, 'Please verify your email address');
- }
- if (error.message.includes('restriction')) {
- return ErrorResponseService.sendUnauthorized(res, 'Please verify your email address');
- }
- if (error.message.includes('deactivated')) {
- return ErrorResponseService.sendUnauthorized(res, 'Account has been deactivated');
- }
- }
-
- return ErrorResponseService.sendInternalServerError(res);
- }
-});
-
-// Create user endpoint
-userRouter.post('/create',
- ValidationMiddleware.combine([
- ValidationMiddleware.validateRequiredFields(['username', 'email', 'password']),
- ValidationMiddleware.validateEmailFormat(['email']),
- ValidationMiddleware.validateStringLength({
- username: { min: 3, max: 50 },
- password: { min: 6, max: 100 }
- })
- ]),
- async (req, res) => {
- try {
- logRequest('Create user endpoint accessed', req, res, {
- username: req.body.username,
- email: req.body.email
- });
-
- const acceptLanguage = req.header('Accept-Language') || 'en';
- const language : 'hu' | 'de' | 'en' = acceptLanguage.toLowerCase().startsWith('hu') ? 'hu' :
- acceptLanguage.toLowerCase().startsWith('de') ? 'de' : 'en';
-
- const result = await container.createUserCommandHandler.execute({ ...req.body, language });
-
- logRequest('User created successfully', req, res, {
- username: result.username
- });
-
- res.status(201).json(result);
-
- } catch (error) {
- // Don't log here since CreateUserCommandHandler already logs system errors
- // Only log validation/user input errors at router level
-
- if (error instanceof Error) {
- if (error.message.includes('already exists')) {
- return ErrorResponseService.sendConflict(res, error.message);
- }
- if (error.message.includes('validation')) {
- return ErrorResponseService.sendBadRequest(res, error.message);
- }
- // Log unexpected errors that weren't handled by the command handler
- if (!error.message.includes('Failed to create user')) {
- logError('Unexpected create user endpoint error', error as Error, req, res);
- }
- }
-
- return ErrorResponseService.sendInternalServerError(res);
- }
-});
-
-// Get user profile (current user)
-userRouter.get('/profile', authRequired, async (req, res) => {
- try {
- const userId = (req as any).user.userId;
-
- logRequest('Get user profile endpoint accessed', req, res, { userId });
-
- const result = await container.getUserByIdQueryHandler.execute({ id: userId });
-
- if (!result) {
- logWarning('User profile not found', { userId }, req, res);
- return ErrorResponseService.sendNotFound(res, 'User not found');
- }
-
- logRequest('User profile retrieved successfully', req, res, {
- userId,
- username: result.username
- });
-
- res.json(result);
-
- } catch (error) {
- logError('Get user profile endpoint error', error as Error, req, res);
- return ErrorResponseService.sendInternalServerError(res);
- }
-});
-
-// Update user profile (current user)
-userRouter.patch('/profile', authRequired, async (req, res) => {
- try {
- const userId = (req as any).user.userId;
-
- logRequest('Update user profile endpoint accessed', req, res, {
- userId,
- fieldsToUpdate: Object.keys(req.body)
- });
-
- const result = await container.updateUserCommandHandler.execute({ id: userId, ...req.body });
-
- if (!result) {
- return ErrorResponseService.sendNotFound(res, 'User not found');
- }
-
- logRequest('User profile updated successfully', req, res, {
- userId,
- username: result.username
- });
-
- res.json(result);
-
- } catch (error) {
- logError('Update user profile endpoint error', error as Error, req, res);
-
- if (error instanceof Error) {
- if (error.message.includes('already exists')) {
- return ErrorResponseService.sendConflict(res, error.message);
- }
- if (error.message.includes('validation')) {
- return ErrorResponseService.sendBadRequest(res, error.message);
- }
- }
-
- return ErrorResponseService.sendInternalServerError(res);
- }
-});
-
-//Soft delete user (current user)
-userRouter.delete('/profile', authRequired, async (req, res) => {
- try {
- const userId = (req as any).user.userId;
- const result = await container.deleteUserCommandHandler.execute({ id: userId, soft: true });
- logRequest('User soft deleted successfully', req, res, { userId });
- res.json({ success: result });
- } catch (error) {
- logError('Soft delete user endpoint error', error as Error, req, res);
- return ErrorResponseService.sendInternalServerError(res);
- }
-});
-
-//logout user (current user)
-userRouter.post('/logout', authRequired, async (req, res) => {
- try {
- const userId = (req as any).user.userId;
- await container.logoutCommandHandler.execute(userId, res, req);
- logRequest('User logged out successfully', req, res, { userId });
- res.json({ success: true });
- } catch (error) {
- logError('Logout user endpoint error', error as Error, req, res);
- return ErrorResponseService.sendInternalServerError(res);
- }
-});
-
-// Refresh token endpoint
-userRouter.post('/refresh-token', async (req, res) => {
- try {
- logRequest('Token refresh endpoint accessed', req, res);
-
- const jwtService = container.jwtService;
- const newTokenPair = jwtService.attemptTokenRefresh(req, res);
-
- if (newTokenPair) {
- logRequest('Token refresh successful', req, res);
- res.json({
- success: true,
- message: 'Tokens refreshed successfully',
- accessToken: newTokenPair.accessToken,
- refreshToken: newTokenPair.refreshToken
- });
- } else {
- logWarning('Token refresh failed - invalid or missing refresh token', undefined, req, res);
- return ErrorResponseService.sendUnauthorized(res, 'Invalid or expired refresh token');
- }
- } catch (error) {
- logError('Refresh token endpoint error', error as Error, req, res);
- return ErrorResponseService.sendInternalServerError(res);
- }
-});
-
-// Email verification endpoint
-userRouter.post('/verify-email/:token', async (req, res) => {
- try {
- const { token } = req.params;
-
- logRequest('Email verification endpoint accessed', req, res, {
- tokenPrefix: token.substring(0, 8) + '...'
- });
-
- if (!token) {
- return ErrorResponseService.sendBadRequest(res, 'Verification token is required');
- }
-
- const result = await container.verifyEmailCommandHandler.execute({ token });
-
- if (result) {
- logAuth('Email verification successful', undefined, { tokenPrefix: token.substring(0, 8) + '...' }, req, res);
- res.json({ success: true, message: 'Email verified successfully' });
- } else {
- throw new Error('Email verification failed');
- }
-
- } catch (error) {
- logError('Email verification endpoint error', error as Error, req, res);
-
- if (error instanceof Error) {
- if (error.message.includes('Invalid') || error.message.includes('expired')) {
- return ErrorResponseService.sendBadRequest(res, 'Invalid or expired verification token');
- }
- }
-
- return ErrorResponseService.sendInternalServerError(res);
- }
-});
-
-// Forgot password request endpoint
-userRouter.post('/forgot-password',
- ValidationMiddleware.combine([
- ValidationMiddleware.validateRequiredFields(['email']),
- ValidationMiddleware.validateEmailFormat(['email'])
- ]),
- async (req, res) => {
- try {
- const { email } = req.body;
- const acceptLanguage = req.header('Accept-Language') || 'en';
- const language: 'hu' | 'de' | 'en' = acceptLanguage.toLowerCase().startsWith('hu') ? 'hu' :
- acceptLanguage.toLowerCase().startsWith('de') ? 'de' : 'en';
-
- logRequest('Forgot password endpoint accessed', req, res, { email });
-
- const result = await container.requestPasswordResetCommandHandler.execute({ language, email });
-
- if (result) {
- logAuth('Password reset request successful', undefined, { email }, req, res);
- res.json({
- success: true,
- message: 'If an account with this email exists, a password reset link has been sent'
- });
- } else {
- throw new Error('Password reset request failed');
- }
-
- } catch (error) {
- logError('Forgot password endpoint error', error as Error, req, res);
-
- // Always return success for security (don't reveal if email exists)
- res.json({
- success: true,
- message: 'If an account with this email exists, a password reset link has been sent'
- });
- }
-});
-
-// Reset password endpoint
-userRouter.post('/reset-password',
- ValidationMiddleware.combine([
- ValidationMiddleware.validateRequiredFields(['token', 'newPassword']),
- ValidationMiddleware.validateStringLength({
- newPassword: { min: 6, max: 100 }
- })
- ]),
- async (req, res) => {
- try {
- const { token, newPassword } = req.body;
-
- logRequest('Reset password endpoint accessed', req, res, {
- tokenPrefix: token.substring(0, 8) + '...'
- });
-
- const result = await container.resetPasswordCommandHandler.execute({ token, newPassword });
-
- if (result) {
- logAuth('Password reset successful', undefined, { tokenPrefix: token.substring(0, 8) + '...' }, req, res);
- res.json({ success: true, message: 'Password reset successfully' });
- } else {
- throw new Error('Password reset failed');
- }
-
- } catch (error) {
- logError('Reset password endpoint error', error as Error, req, res);
-
- if (error instanceof Error) {
- if (error.message.includes('Invalid') || error.message.includes('expired')) {
- return ErrorResponseService.sendBadRequest(res, 'Invalid or expired reset token');
- }
- if (error.message.includes('Password validation')) {
- return ErrorResponseService.sendBadRequest(res, error.message);
- }
- }
-
- return ErrorResponseService.sendInternalServerError(res);
- }
-});
-
-export default userRouter;
diff --git a/SerpentRace_Backend/src/Api/swagger/swaggerConfig.ts b/SerpentRace_Backend/src/Api/swagger/swaggerConfig.ts
deleted file mode 100644
index 1f2e31ef..00000000
--- a/SerpentRace_Backend/src/Api/swagger/swaggerConfig.ts
+++ /dev/null
@@ -1,101 +0,0 @@
-import swaggerJSDoc from 'swagger-jsdoc';
-import path from 'path';
-
-export const swaggerOptions = {
- definition: {
- openapi: '3.0.0',
- info: {
- title: 'SerpentRace API',
- version: '1.0.0',
- description: 'Comprehensive API documentation for SerpentRace Backend',
- contact: {
- name: 'SerpentRace Development Team',
- email: 'dev@serpentrace.com'
- },
- license: {
- name: 'MIT',
- url: 'https://opensource.org/licenses/MIT'
- }
- },
- servers: [
- {
- url: 'http://localhost:3001',
- description: 'Local development server'
- },
- {
- url: 'http://localhost:3000',
- description: 'Local development server (alt)'
- },
- {
- url: 'https://api.serpentrace.com',
- description: 'Production server'
- }
- ],
- components: {
- securitySchemes: {
- bearerAuth: {
- type: 'http',
- scheme: 'bearer',
- bearerFormat: 'JWT',
- description: 'Enter JWT token obtained from /api/users/login'
- }
- }
- },
- security: [{ bearerAuth: [] }],
- tags: [
- {
- name: 'Users',
- description: 'User authentication and profile management'
- },
- {
- name: 'Organizations',
- description: 'Organization management and authentication'
- },
- {
- name: 'Decks',
- description: 'Deck creation, management, and gameplay'
- },
- {
- name: 'Chats',
- description: 'Real-time chat and messaging system'
- },
- {
- name: 'Contacts',
- description: 'Contact form and support requests'
- },
- {
- name: 'Deck Import/Export',
- description: 'Import and export deck functionality'
- },
- {
- name: 'Games',
- description: 'Game management and gameplay'
- },
- {
- name: 'Admin - Users',
- description: 'Admin user management operations'
- },
- {
- name: 'Admin - Decks',
- description: 'Admin deck management operations'
- },
- {
- name: 'Admin - Organizations',
- description: 'Admin organization management operations'
- },
- {
- name: 'Admin - Chats',
- description: 'Admin chat management operations'
- },
- {
- name: 'Admin - Contacts',
- description: 'Admin contact management operations'
- }
- ]
- },
- apis: [
- './src/Api/swagger/swaggerDefinitionsFixed.ts'
- ],
-};
-
-export const swaggerSpec = swaggerJSDoc(swaggerOptions);
diff --git a/SerpentRace_Backend/src/Api/swagger/swaggerDefinitions.ts b/SerpentRace_Backend/src/Api/swagger/swaggerDefinitions.ts
deleted file mode 100644
index eef90dac..00000000
--- a/SerpentRace_Backend/src/Api/swagger/swaggerDefinitions.ts
+++ /dev/null
@@ -1,1694 +0,0 @@
-/**
- * @swagger
- * components:
-<<<<<<< HEAD
-<<<<<<< HEAD
-=======
- * securitySchemes:
- * bearerAuth:
- * type: http
- * scheme: bearer
- * bearerFormat: JWT
->>>>>>> origin/main
-=======
->>>>>>> 83fad59878db015ec8d86bdec1ecbbca0baddfd2
- * schemas:
- * User:
- * type: object
- * properties:
- * id:
- * type: string
- * format: uuid
- * username:
- * type: string
- * email:
- * type: string
- * format: email
- * fname:
- * type: string
- * lname:
- * type: string
- * phone:
- * type: string
- * nullable: true
- * type:
- * type: string
- * state:
- * type: integer
- * regdate:
- * type: string
- * format: date-time
- * updatedate:
- * type: string
- * format: date-time
- * orgid:
- * type: string
- * nullable: true
- *
- * CreateUserRequest:
- * type: object
- * required:
- * - username
- * - email
- * - password
- * - fname
- * - lname
- * - type
- * properties:
- * username:
- * type: string
- * email:
- * type: string
- * format: email
- * password:
- * type: string
- * format: password
- * fname:
- * type: string
- * lname:
- * type: string
- * phone:
- * type: string
- * type:
- * type: string
- *
- * LoginRequest:
- * type: object
- * required:
- * - username
- * - password
- * properties:
- * username:
- * type: string
- * password:
- * type: string
- * format: password
- *
- * LoginResponse:
- * type: object
- * properties:
- * token:
- * type: string
- * user:
- * $ref: '#/components/schemas/User'
- * requiresOrgReauth:
- * type: boolean
- * orgLoginUrl:
- * type: string
- * organizationName:
- * type: string
- *
- * UpdateProfileRequest:
- * type: object
- * properties:
- * fname:
- * type: string
- * lname:
- * type: string
- * phone:
- * type: string
- * email:
- * type: string
- * format: email
- *
-<<<<<<< HEAD
- * ForgotPasswordRequest:
- * type: object
- * required:
- * - email
- * properties:
- * email:
- * type: string
- * format: email
- *
- * ResetPasswordRequest:
- * type: object
- * required:
- * - token
- * - newPassword
- * properties:
- * token:
- * type: string
- * newPassword:
- * type: string
- * format: password
- * minLength: 6
- * maxLength: 100
- *
- * AuthSuccessResponse:
- * type: object
- * properties:
- * success:
- * type: boolean
- * message:
- * type: string
- *
-=======
->>>>>>> origin/main
- * Organization:
- * type: object
- * properties:
- * id:
- * type: string
- * format: uuid
- * name:
- * type: string
- * contactfname:
- * type: string
- * contactlname:
- * type: string
- * contactphone:
- * type: string
- * contactemail:
- * type: string
- * format: email
- * state:
- * type: integer
- * regdate:
- * type: string
- * format: date-time
- * updatedate:
- * type: string
- * format: date-time
- * url:
- * type: string
- * nullable: true
- * userinorg:
- * type: integer
- * maxOrganizationalDecks:
- * type: integer
- *
- * Deck:
- * type: object
- * properties:
- * id:
- * type: string
- * format: uuid
- * name:
- * type: string
- * type:
- * type: integer
- * enum: [0, 1, 2, 3]
- * description: 0=JOKER, 1=LUCK, 2=QUESTION, 3=GENERAL
- * userid:
- * type: string
- * format: uuid
- * creationdate:
- * type: string
- * format: date-time
- * cards:
- * type: array
- * items:
- * type: object
- * playedNumber:
- * type: integer
- * ctype:
- * type: integer
- * enum: [0, 1, 2]
- * description: 0=PUBLIC, 1=ORGANIZATIONAL, 2=PRIVATE
- * updatedate:
- * type: string
- * format: date-time
- * state:
- * type: integer
- * enum: [0, 1, 2]
- * description: 0=ACTIVE, 1=INACTIVE, 2=SOFT_DELETE
- * organization:
- * $ref: '#/components/schemas/Organization'
- * nullable: true
- *
- * CreateDeckRequest:
- * type: object
- * required:
- * - name
- * - type
- * - cards
- * properties:
- * name:
- * type: string
- * type:
- * type: integer
- * cards:
- * type: array
- * items:
- * type: object
- * ctype:
- * type: integer
- *
- * Contact:
- * type: object
- * properties:
- * id:
- * type: string
- * format: uuid
- * name:
- * type: string
- * email:
- * type: string
- * format: email
- * userid:
- * type: string
- * format: uuid
- * nullable: true
- * type:
- * type: integer
- * enum: [0, 1, 2]
- * description: 0=QUESTION, 1=BUG_REPORT, 2=SUGGESTION
- * txt:
- * type: string
- * state:
- * type: integer
- * createDate:
- * type: string
- * format: date-time
- * updateDate:
- * type: string
- * format: date-time
- * adminResponse:
- * type: string
- * nullable: true
- * responseDate:
- * type: string
- * format: date-time
- * nullable: true
- * respondedBy:
- * type: string
- * nullable: true
- *
- * CreateContactRequest:
- * type: object
- * required:
- * - name
- * - email
- * - type
- * - txt
- * properties:
- * name:
- * type: string
- * email:
- * type: string
- * format: email
- * type:
- * type: integer
- * txt:
- * type: string
- *
- * Chat:
- * type: object
- * properties:
- * id:
- * type: string
- * format: uuid
- * name:
- * type: string
- * type:
- * type: integer
- * participants:
- * type: array
- * items:
- * type: string
- * creatorId:
- * type: string
- * gameId:
- * type: string
- * nullable: true
- * createDate:
- * type: string
- * format: date-time
- * updateDate:
- * type: string
- * format: date-time
- * state:
- * type: integer
- *
- * ChatMessage:
- * type: object
- * properties:
- * id:
- * type: string
- * format: uuid
- * senderId:
- * type: string
- * senderName:
- * type: string
- * message:
- * type: string
- * timestamp:
- * type: string
- * format: date-time
- * chatId:
- * type: string
- *
-<<<<<<< HEAD
-<<<<<<< HEAD
-=======
->>>>>>> 83fad59878db015ec8d86bdec1ecbbca0baddfd2
- * Game:
- * type: object
- * properties:
- * id:
- * type: string
- * format: uuid
- * gamecode:
- * type: string
- * maxplayers:
- * type: integer
- * logintype:
- * type: integer
- * gamedecks:
- * type: array
- * players:
- * type: array
- * items:
- * type: string
- * started:
- * type: boolean
- * finished:
- * type: boolean
- * state:
- * type: integer
- * createdate:
- * type: string
- * format: date-time
- *
-<<<<<<< HEAD
-=======
->>>>>>> origin/main
-=======
->>>>>>> 83fad59878db015ec8d86bdec1ecbbca0baddfd2
- * Error:
- * type: object
- * properties:
- * error:
- * type: string
- * timestamp:
- * type: string
- * format: date-time
- * details:
- * type: string
-<<<<<<< HEAD
-<<<<<<< HEAD
-=======
->>>>>>> 83fad59878db015ec8d86bdec1ecbbca0baddfd2
- */
-/**
- * @swagger
- *
- * /api/users/login:
- * post:
- * tags: [Users]
- * summary: User login
- * description: Authenticate user and return JWT token
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/LoginRequest'
- * responses:
- * 200:
- * description: Login successful
-<<<<<<< HEAD
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/LoginResponse'
- * 401:
- * description: Invalid credentials
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Error'
- *
-=======
- *
- * paths:
- * /api/users/login:
- * post:
- * tags: [Users]
- * summary: User login
- * description: Authenticate user and return JWT token
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/LoginRequest'
- * responses:
- * 200:
- * description: Login successful
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/LoginResponse'
- * 401:
- * description: Invalid credentials
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Error'
->>>>>>> origin/main
-=======
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/LoginResponse'
- * 401:
- * description: Invalid credentials
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Error'
- *
->>>>>>> 83fad59878db015ec8d86bdec1ecbbca0baddfd2
- *
- * /api/users/create:
- * post:
- * tags: [Users]
- * summary: Create new user
- * description: Register a new user account
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/CreateUserRequest'
- * responses:
- * 201:
- * description: User created successfully
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/User'
- * 400:
- * description: Validation error
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Error'
- *
- * /api/users/profile:
- * get:
- * tags: [Users]
- * summary: Get user profile
- * description: Get current user's profile information
- * security:
- * - bearerAuth: []
- * responses:
- * 200:
- * description: User profile data
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/User'
- * 401:
- * description: Unauthorized
- * patch:
- * tags: [Users]
- * summary: Update user profile
- * description: Update current user's profile information
- * security:
- * - bearerAuth: []
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/UpdateProfileRequest'
- * responses:
- * 200:
- * description: Profile updated successfully
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/User'
- * 400:
- * description: Validation error
- * 401:
- * description: Unauthorized
- *
- * /api/organizations/page/{from}/{to}:
- * get:
- * tags: [Organizations]
- * summary: Get organizations by page
- * description: Retrieve paginated list of organizations
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: from
- * in: path
- * required: true
- * schema:
- * type: integer
- * - name: to
- * in: path
- * required: true
- * schema:
- * type: integer
- * responses:
- * 200:
- * description: Paginated organizations
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * organizations:
- * type: array
- * items:
- * $ref: '#/components/schemas/Organization'
- * totalCount:
- * type: integer
- *
- * /api/organizations/search:
- * get:
- * tags: [Organizations]
- * summary: Search organizations
- * description: Search organizations by query
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: query
- * in: query
- * required: true
- * schema:
- * type: string
- * - name: from
- * in: query
- * required: true
- * schema:
- * type: integer
- * - name: to
- * in: query
- * required: true
- * schema:
- * type: integer
- * responses:
- * 200:
- * description: Search results
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * results:
- * type: array
- * items:
- * $ref: '#/components/schemas/Organization'
- * totalCount:
- * type: integer
- *
- * /api/organizations/{orgId}/login-url:
- * get:
- * tags: [Organizations]
- * summary: Get organization login URL
- * description: Get OAuth login URL for organization
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: orgId
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Login URL
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * loginUrl:
- * type: string
- *
- * /api/organizations/auth-callback:
- * post:
- * tags: [Organizations]
- * summary: OAuth callback
- * description: Handle OAuth callback from organization
- * security:
- * - bearerAuth: []
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * code:
- * type: string
- * state:
- * type: string
- * responses:
- * 200:
- * description: Authentication successful
- * 400:
- * description: Invalid callback data
- *
- * /api/decks/page/{from}/{to}:
- * get:
- * tags: [Decks]
- * summary: Get decks by page
- * description: Retrieve paginated list of decks
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: from
- * in: path
- * required: true
- * schema:
- * type: integer
- * - name: to
- * in: path
- * required: true
- * schema:
- * type: integer
- * responses:
- * 200:
- * description: Paginated decks
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * decks:
- * type: array
- * items:
- * $ref: '#/components/schemas/Deck'
- * totalCount:
- * type: integer
- *
- * /api/decks:
- * post:
- * tags: [Decks]
- * summary: Create deck
- * description: Create a new deck
- * security:
- * - bearerAuth: []
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/CreateDeckRequest'
- * responses:
- * 201:
- * description: Deck created successfully
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Deck'
- *
- * /api/decks/search:
- * get:
- * tags: [Decks]
- * summary: Search decks
- * description: Search decks by query
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: query
- * in: query
- * required: true
- * schema:
- * type: string
- * - name: from
- * in: query
- * required: true
- * schema:
- * type: integer
- * - name: to
- * in: query
- * required: true
- * schema:
- * type: integer
- * responses:
- * 200:
- * description: Search results
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * results:
- * type: array
- * items:
- * $ref: '#/components/schemas/Deck'
- * totalCount:
- * type: integer
- *
- * /api/decks/{id}:
- * get:
- * tags: [Decks]
- * summary: Get deck by ID
- * description: Retrieve a specific deck by ID
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Deck details
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Deck'
- * 404:
- * description: Deck not found
- * put:
- * tags: [Decks]
- * summary: Update deck
- * description: Update an existing deck
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/CreateDeckRequest'
- * responses:
- * 200:
- * description: Deck updated successfully
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Deck'
- * delete:
- * tags: [Decks]
- * summary: Delete deck
- * description: Delete a deck (soft delete)
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 204:
- * description: Deck deleted successfully
- * 404:
- * description: Deck not found
- *
- * /api/chats/user-chats:
- * get:
- * tags: [Chats]
- * summary: Get user chats
- * description: Get all chats for the current user
- * security:
- * - bearerAuth: []
- * responses:
- * 200:
- * description: User chats
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: '#/components/schemas/Chat'
- *
- * /api/chats/history/{chatId}:
- * get:
- * tags: [Chats]
- * summary: Get chat history
- * description: Get message history for a chat
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: chatId
- * in: path
- * required: true
- * schema:
- * type: string
- * - name: page
- * in: query
- * schema:
- * type: integer
- * - name: limit
- * in: query
- * schema:
- * type: integer
- * responses:
- * 200:
- * description: Chat history
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: '#/components/schemas/ChatMessage'
- *
- * /api/chats/create:
- * post:
- * tags: [Chats]
- * summary: Create chat
- * description: Create a new chat room
- * security:
- * - bearerAuth: []
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * type: object
- * required:
- * - name
- * - gameId
- * properties:
- * name:
- * type: string
- * gameId:
- * type: string
- * password:
- * type: string
- * nullable: true
- * responses:
- * 201:
- * description: Chat created successfully
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Chat'
- *
- * /api/chats/message:
- * post:
- * tags: [Chats]
- * summary: Send message
- * description: Send a message to a chat
- * security:
- * - bearerAuth: []
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * type: object
- * required:
- * - chatId
- * - message
- * properties:
- * chatId:
- * type: string
- * message:
- * type: string
- * responses:
- * 201:
- * description: Message sent successfully
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/ChatMessage'
- *
- * /api/chats/archive/{chatId}:
- * post:
- * tags: [Chats]
- * summary: Archive chat
- * description: Archive a chat room
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: chatId
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Chat archived successfully
- * 404:
- * description: Chat not found
- *
- * /api/chats/restore/{chatId}:
- * post:
- * tags: [Chats]
- * summary: Restore chat
- * description: Restore an archived chat room
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: chatId
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Chat restored successfully
- * 404:
- * description: Chat not found
- *
- * /api/chats/archived/game/{gameId}:
- * get:
- * tags: [Chats]
- * summary: Get archived chats by game
- * description: Get all archived chats for a specific game
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: gameId
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Archived chats
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: '#/components/schemas/Chat'
- *
- * /api/deck-import-export/export/{deckId}:
- * get:
- * tags: [Import/Export]
- * summary: Export deck
- * description: Export a deck as JSON or .spr file
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: deckId
- * in: path
- * required: true
- * schema:
- * type: string
- * - name: format
- * in: query
- * schema:
- * type: string
- * enum: [json, spr]
- * default: json
- * responses:
- * 200:
- * description: Deck exported successfully
- * content:
- * application/json:
- * schema:
- * type: object
- * application/octet-stream:
- * schema:
- * type: string
- * format: binary
- *
- * /api/deck-import-export/import:
- * post:
- * tags: [Import/Export]
- * summary: Import deck
- * description: Import a deck from JSON or .spr file
- * security:
- * - bearerAuth: []
- * requestBody:
- * required: true
- * content:
- * multipart/form-data:
- * schema:
- * type: object
- * properties:
- * file:
- * type: string
- * format: binary
- * responses:
- * 201:
- * description: Deck imported successfully
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Deck'
- *
- * /api/admin/users/page/{from}/{to}:
- * get:
- * tags: [Admin - Users]
- * summary: Get users by page (Admin)
- * description: Admin endpoint to retrieve paginated list of users
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: from
- * in: path
- * required: true
- * schema:
- * type: integer
- * - name: to
- * in: path
- * required: true
- * schema:
- * type: integer
- * responses:
- * 200:
- * description: Paginated users
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * users:
- * type: array
- * items:
- * $ref: '#/components/schemas/User'
- * totalCount:
- * type: integer
- *
- * /api/admin/users/{userId}:
- * get:
- * tags: [Admin - Users]
- * summary: Get user by ID (Admin)
- * description: Admin endpoint to get specific user details
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: userId
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: User details
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/User'
- * delete:
- * tags: [Admin - Users]
- * summary: Delete user (Admin)
- * description: Admin endpoint to delete a user
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: userId
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 204:
- * description: User deleted successfully
- *
- * /api/admin/users/search/{searchTerm}:
- * get:
- * tags: [Admin - Users]
- * summary: Search users (Admin)
- * description: Admin endpoint to search users
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: searchTerm
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Search results
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: '#/components/schemas/User'
- *
- * /api/admin/users/{userId}/deactivate:
- * post:
- * tags: [Admin - Users]
- * summary: Deactivate user (Admin)
- * description: Admin endpoint to deactivate a user
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: userId
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: User deactivated successfully
- *
- * /api/admin/decks/page/{from}/{to}:
- * get:
- * tags: [Admin - Decks]
- * summary: Get decks by page (Admin)
- * description: Admin endpoint to retrieve paginated list of decks
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: from
- * in: path
- * required: true
- * schema:
- * type: integer
- * - name: to
- * in: path
- * required: true
- * schema:
- * type: integer
- * responses:
- * 200:
- * description: Paginated decks
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * decks:
- * type: array
- * items:
- * $ref: '#/components/schemas/Deck'
- * totalCount:
- * type: integer
- *
- * /api/admin/decks/{id}:
- * get:
- * tags: [Admin - Decks]
- * summary: Get deck by ID (Admin)
- * description: Admin endpoint to get specific deck details
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Deck details
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Deck'
- *
- * /api/admin/decks/search/{searchTerm}:
- * get:
- * tags: [Admin - Decks]
- * summary: Search decks (Admin)
- * description: Admin endpoint to search decks
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: searchTerm
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Search results
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: '#/components/schemas/Deck'
- *
- * /api/admin/decks/{id}/hard:
- * delete:
- * tags: [Admin - Decks]
- * summary: Hard delete deck (Admin)
- * description: Admin endpoint to permanently delete a deck
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 204:
- * description: Deck permanently deleted
- *
- * /api/admin/organizations:
- * post:
- * tags: [Admin - Organizations]
- * summary: Create organization (Admin)
- * description: Admin endpoint to create a new organization
- * security:
- * - bearerAuth: []
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * type: object
- * required:
- * - name
- * properties:
- * name:
- * type: string
- * description:
- * type: string
- * responses:
- * 201:
- * description: Organization created successfully
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Organization'
- *
- * /api/admin/organizations/page/{from}/{to}:
- * get:
- * tags: [Admin - Organizations]
- * summary: Get organizations by page (Admin)
- * description: Admin endpoint to retrieve paginated list of organizations
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: from
- * in: path
- * required: true
- * schema:
- * type: integer
- * - name: to
- * in: path
- * required: true
- * schema:
- * type: integer
- * responses:
- * 200:
- * description: Paginated organizations
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * organizations:
- * type: array
- * items:
- * $ref: '#/components/schemas/Organization'
- * totalCount:
- * type: integer
- *
- * /api/admin/organizations/{id}:
- * get:
- * tags: [Admin - Organizations]
- * summary: Get organization by ID (Admin)
- * description: Admin endpoint to get specific organization details
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Organization details
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Organization'
- * delete:
- * tags: [Admin - Organizations]
- * summary: Delete organization (Admin)
- * description: Admin endpoint to soft delete an organization
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 204:
- * description: Organization deleted successfully
- *
- * /api/admin/organizations/search/{searchTerm}:
- * get:
- * tags: [Admin - Organizations]
- * summary: Search organizations (Admin)
- * description: Admin endpoint to search organizations
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: searchTerm
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Search results
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: '#/components/schemas/Organization'
- *
- * /api/admin/organizations/{id}/hard:
- * delete:
- * tags: [Admin - Organizations]
- * summary: Hard delete organization (Admin)
- * description: Admin endpoint to permanently delete an organization
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 204:
- * description: Organization permanently deleted
- *
- * /api/admin/chats/page/{from}/{to}:
- * get:
- * tags: [Admin - Chats]
- * summary: Get chats by page (Admin)
- * description: Admin endpoint to retrieve paginated list of chats
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: from
- * in: path
- * required: true
- * schema:
- * type: integer
- * - name: to
- * in: path
- * required: true
- * schema:
- * type: integer
- * responses:
- * 200:
- * description: Paginated chats
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * chats:
- * type: array
- * items:
- * $ref: '#/components/schemas/Chat'
- * totalCount:
- * type: integer
- *
- * /api/admin/chats/{id}:
- * get:
- * tags: [Admin - Chats]
- * summary: Get chat by ID (Admin)
- * description: Admin endpoint to get specific chat details
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Chat details
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Chat'
- *
- * /api/admin/contacts/page/{from}/{to}:
- * get:
- * tags: [Admin - Contacts]
- * summary: Get contacts by page (Admin)
- * description: Admin endpoint to retrieve paginated list of contacts
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: from
- * in: path
- * required: true
- * schema:
- * type: integer
- * - name: to
- * in: path
- * required: true
- * schema:
- * type: integer
- * responses:
- * 200:
- * description: Paginated contacts
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * contacts:
- * type: array
- * items:
- * $ref: '#/components/schemas/Contact'
- * totalCount:
- * type: integer
- *
- * /api/admin/contacts/{id}:
- * get:
- * tags: [Admin - Contacts]
- * summary: Get contact by ID (Admin)
- * description: Admin endpoint to get specific contact details
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Contact details
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Contact'
- *
- * /api/admin/contacts/search/{searchTerm}:
- * get:
- * tags: [Admin - Contacts]
- * summary: Search contacts (Admin)
- * description: Admin endpoint to search contacts
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: searchTerm
- * in: path
- * required: true
- * schema:
- * type: string
- * - name: includeDeleted
- * in: query
- * required: true
- * schema:
- * type: boolean
- * responses:
- * 200:
- * description: Search results
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: '#/components/schemas/Contact'
- *
- * /api/contacts:
- * post:
- * tags: [Contacts]
- * summary: Create contact
- * description: Create a new contact message
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/CreateContactRequest'
- * responses:
- * 201:
- * description: Contact created successfully
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Contact'
-<<<<<<< HEAD
-<<<<<<< HEAD
-=======
->>>>>>> 83fad59878db015ec8d86bdec1ecbbca0baddfd2
- *
- * /api/games/start:
- * post:
- * summary: Start a new game
- * tags: [Games]
- * security:
- * - bearerAuth: []
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * type: object
- * required:
- * - deckids
- * - maxplayers
- * - logintype
- * properties:
- * deckids:
- * type: array
- * items:
- * type: string
- * description: Array of deck IDs (must include all 3 types LUCK, JOKER, QUESTION)
- * maxplayers:
- * type: integer
- * minimum: 2
- * maximum: 8
- * description: Maximum number of players allowed in the game
- * logintype:
- * type: integer
- * enum: [0, 1, 2]
- * description: How players can join (PUBLIC=0, PRIVATE=1, ORGANIZATION=2)
- * responses:
- * 200:
- * description: Game started successfully
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * id:
- * type: string
- * description: Game UUID
- * gamecode:
- * type: string
- * description: 6-character game code for joining
- * maxplayers:
- * type: integer
- * logintype:
- * type: integer
- * gamedecks:
- * type: array
- * description: Shuffled game decks
- * players:
- * type: array
- * items:
- * type: string
- * started:
- * type: boolean
- * finished:
- * type: boolean
- * state:
- * type: integer
- * description: Game state (WAITING=0, ACTIVE=1, FINISHED=2, CANCELLED=3)
- * createdate:
- * type: string
- * format: date-time
- * 400:
- * description: Invalid input parameters
- * 401:
- * description: Authentication required
- * 500:
- * description: Internal server error
- *
- * /api/games/join:
- * post:
- * summary: Join a game (automatically detects game type)
- * description: Join any game by providing the game code. The system automatically determines if authentication is required based on the game type.
- * tags: [Games]
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * type: object
- * required:
- * - gameCode
- * properties:
- * gameCode:
- * type: string
- * description: 6-character game code
- * example: "ABC123"
- * playerName:
- * type: string
- * description: Display name for the player (required for public games, optional for authenticated games)
- * example: "John Doe"
- * responses:
- * 200:
- * description: Successfully joined the game
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Game'
- * 400:
- * description: Invalid input or missing required fields
- * 401:
- * description: Authentication required for this game type
- * 403:
- * description: Organization membership required
- * 404:
- * description: Game not found
- * 409:
- * description: Game is full or not accepting players
- * 500:
- * description: Internal server error
- *
- * /api/games/{gameId}/start:
- * post:
- * summary: Start gameplay for an existing game
- * description: Initialize gameplay by setting all player positions to 0 and assigning random turn order. This is separate from game creation.
- * tags: [Games]
- * parameters:
- * - in: path
- * name: gameId
- * required: true
- * schema:
- * type: string
- * description: The ID of the game to start
- * responses:
- * 200:
- * description: Game started successfully
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * message:
- * type: string
- * example: "Game started successfully"
- * gameId:
- * type: string
- * example: "game123"
- * playerCount:
- * type: number
- * example: 4
- * 400:
- * description: Invalid input or game cannot be started
- * 401:
- * description: Authentication required
- * 403:
- * description: Only game master can start the game
- * 404:
- * description: Game not found
- * 409:
- * description: Game already started or not ready to start
- * 500:
- * description: Internal server error
-<<<<<<< HEAD
-=======
->>>>>>> origin/main
-=======
->>>>>>> 83fad59878db015ec8d86bdec1ecbbca0baddfd2
- */
-
-export {};
diff --git a/SerpentRace_Backend/src/Api/swagger/swaggerDefinitionsFixed.ts b/SerpentRace_Backend/src/Api/swagger/swaggerDefinitionsFixed.ts
deleted file mode 100644
index 1f019805..00000000
--- a/SerpentRace_Backend/src/Api/swagger/swaggerDefinitionsFixed.ts
+++ /dev/null
@@ -1,2788 +0,0 @@
-/**
- * @swagger
- * components:
- * schemas:
- * User:
- * type: object
- * properties:
- * id:
- * type: string
- * format: uuid
- * username:
- * type: string
- * email:
- * type: string
- * format: email
- * fname:
- * type: string
- * lname:
- * type: string
- * phone:
- * type: string
- * nullable: true
- * type:
- * type: string
- * state:
- * type: integer
- * regdate:
- * type: string
- * format: date-time
- * updatedate:
- * type: string
- * format: date-time
- * orgid:
- * type: string
- * nullable: true
- *
- * CreateUserRequest:
- * type: object
- * required:
- * - username
- * - email
- * - password
- * - fname
- * - lname
- * - type
- * properties:
- * username:
- * type: string
- * email:
- * type: string
- * format: email
- * password:
- * type: string
- * format: password
- * fname:
- * type: string
- * lname:
- * type: string
- * phone:
- * type: string
- * type:
- * type: string
- *
- * LoginRequest:
- * type: object
- * required:
- * - username
- * - password
- * properties:
- * username:
- * type: string
- * password:
- * type: string
- * format: password
- *
- * LoginResponse:
- * type: object
- * properties:
- * token:
- * type: string
- * user:
- * $ref: '#/components/schemas/User'
- * requiresOrgReauth:
- * type: boolean
- * orgLoginUrl:
- * type: string
- * organizationName:
- * type: string
- *
- * UpdateProfileRequest:
- * type: object
- * properties:
- * fname:
- * type: string
- * lname:
- * type: string
- * phone:
- * type: string
- * email:
- * type: string
- * format: email
- *
- * ForgotPasswordRequest:
- * type: object
- * required:
- * - email
- * properties:
- * email:
- * type: string
- * format: email
- *
- * ResetPasswordRequest:
- * type: object
- * required:
- * - token
- * - newPassword
- * properties:
- * token:
- * type: string
- * newPassword:
- * type: string
- * format: password
- * minLength: 6
- * maxLength: 100
- *
- * AuthSuccessResponse:
- * type: object
- * properties:
- * success:
- * type: boolean
- * message:
- * type: string
- *
- * Organization:
- * type: object
- * properties:
- * id:
- * type: string
- * format: uuid
- * name:
- * type: string
- * contactfname:
- * type: string
- * contactlname:
- * type: string
- * contactphone:
- * type: string
- * contactemail:
- * type: string
- * format: email
- * state:
- * type: integer
- * regdate:
- * type: string
- * format: date-time
- * updatedate:
- * type: string
- * format: date-time
- * url:
- * type: string
- * nullable: true
- * userinorg:
- * type: integer
- * maxOrganizationalDecks:
- * type: integer
- *
- * Deck:
- * type: object
- * properties:
- * id:
- * type: string
- * format: uuid
- * name:
- * type: string
- * type:
- * type: integer
- * enum: [0, 1, 2, 3]
- * description: 0=JOKER, 1=LUCK, 2=QUESTION, 3=GENERAL
- * userid:
- * type: string
- * format: uuid
- * creationdate:
- * type: string
- * format: date-time
- * cards:
- * type: array
- * items:
- * type: object
- * playedNumber:
- * type: integer
- * ctype:
- * type: integer
- * enum: [0, 1, 2]
- * description: 0=PUBLIC, 1=ORGANIZATIONAL, 2=PRIVATE
- * updatedate:
- * type: string
- * format: date-time
- * state:
- * type: integer
- * enum: [0, 1, 2]
- * description: 0=ACTIVE, 1=INACTIVE, 2=SOFT_DELETE
- * organization:
- * $ref: '#/components/schemas/Organization'
- * nullable: true
- *
- * CreateDeckRequest:
- * type: object
- * required:
- * - name
- * - type
- * - cards
- * properties:
- * name:
- * type: string
- * type:
- * type: integer
- * cards:
- * type: array
- * items:
- * type: object
- * ctype:
- * type: integer
- *
- * Chat:
- * type: object
- * properties:
- * id:
- * type: string
- * format: uuid
- * name:
- * type: string
- * type:
- * type: integer
- * participants:
- * type: array
- * items:
- * type: string
- * creatorId:
- * type: string
- * gameId:
- * type: string
- * nullable: true
- * createDate:
- * type: string
- * format: date-time
- * updateDate:
- * type: string
- * format: date-time
- * state:
- * type: integer
- *
- * ChatMessage:
- * type: object
- * properties:
- * id:
- * type: string
- * format: uuid
- * senderId:
- * type: string
- * senderName:
- * type: string
- * message:
- * type: string
- * timestamp:
- * type: string
- * format: date-time
- * chatId:
- * type: string
- *
- * Contact:
- * type: object
- * properties:
- * id:
- * type: string
- * format: uuid
- * name:
- * type: string
- * email:
- * type: string
- * format: email
- * userid:
- * type: string
- * format: uuid
- * nullable: true
- * type:
- * type: integer
- * enum: [0, 1, 2]
- * description: 0=QUESTION, 1=BUG_REPORT, 2=SUGGESTION
- * txt:
- * type: string
- * state:
- * type: integer
- * createDate:
- * type: string
- * format: date-time
- * updateDate:
- * type: string
- * format: date-time
- * adminResponse:
- * type: string
- * nullable: true
- * responseDate:
- * type: string
- * format: date-time
- * nullable: true
- * respondedBy:
- * type: string
- * nullable: true
- *
- * CreateContactRequest:
- * type: object
- * required:
- * - name
- * - email
- * - type
- * - txt
- * properties:
- * name:
- * type: string
- * email:
- * type: string
- * format: email
- * type:
- * type: integer
- * txt:
- * type: string
- *
- * Game:
- * type: object
- * properties:
- * id:
- * type: string
- * format: uuid
- * gamecode:
- * type: string
- * maxplayers:
- * type: integer
- * logintype:
- * type: integer
- * gamedecks:
- * type: array
- * players:
- * type: array
- * items:
- * type: string
- * started:
- * type: boolean
- * finished:
- * type: boolean
- * state:
- * type: integer
- * createdate:
- * type: string
- * format: date-time
- *
- * Error:
- * type: object
- * properties:
- * error:
- * type: string
- * timestamp:
- * type: string
- * format: date-time
- * details:
- * type: string
- */
-
-/**
- * @swagger
- * /api/users/login:
- * post:
- * tags: [Users]
- * summary: User login
- * description: Authenticate user and return JWT token
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/LoginRequest'
- * responses:
- * 200:
- * description: Login successful
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/LoginResponse'
- * 401:
- * description: Invalid credentials
- */
-
-/**
- * @swagger
- * /api/users/create:
- * post:
- * tags: [Users]
- * summary: Create new user
- * description: Register a new user account
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/CreateUserRequest'
- * responses:
- * 201:
- * description: User created successfully
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/User'
- * 400:
- * description: Validation error
- * 409:
- * description: User already exists
- */
-
-/**
- * @swagger
- * /api/users/profile:
- * get:
- * tags: [Users]
- * summary: Get user profile
- * description: Get current user's profile information
- * security:
- * - bearerAuth: []
- * responses:
- * 200:
- * description: User profile data
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/User'
- * 401:
- * description: Unauthorized
- * patch:
- * tags: [Users]
- * summary: Update user profile
- * description: Update current user's profile information
- * security:
- * - bearerAuth: []
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/UpdateProfileRequest'
- * responses:
- * 200:
- * description: Profile updated successfully
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/User'
- * 400:
- * description: Validation error
- * 401:
- * description: Unauthorized
- */
-
-/**
- * @swagger
- * /api/users/verify-email/{token}:
- * get:
- * tags: [Users]
- * summary: Verify email address
- * description: Verify user's email address using verification token
- * parameters:
- * - name: token
- * in: path
- * required: true
- * schema:
- * type: string
- * description: Email verification token
- * responses:
- * 200:
- * description: Email verified successfully
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/AuthSuccessResponse'
- * 400:
- * description: Invalid or expired verification token
- * 500:
- * description: Internal server error
- */
-
-/**
- * @swagger
- * /api/users/forgot-password:
- * post:
- * tags: [Users]
- * summary: Request password reset
- * description: Send password reset email to user
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/ForgotPasswordRequest'
- * responses:
- * 200:
- * description: Password reset email sent (if email exists)
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/AuthSuccessResponse'
- * 400:
- * description: Validation error
- * 500:
- * description: Internal server error
- */
-
-/**
- * @swagger
- * /api/users/reset-password:
- * post:
- * tags: [Users]
- * summary: Reset password
- * description: Reset user password using reset token
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/ResetPasswordRequest'
- * responses:
- * 200:
- * description: Password reset successfully
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/AuthSuccessResponse'
- * 400:
- * description: Invalid token or password validation failed
- * 500:
- * description: Internal server error
- */
-
-/**
- * @swagger
- * /api/organizations/search:
- * get:
- * tags: [Organizations]
- * summary: Search organizations
- * description: Search organizations by query
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: query
- * in: query
- * required: true
- * schema:
- * type: string
- * - name: from
- * in: query
- * required: true
- * schema:
- * type: integer
- * - name: to
- * in: query
- * required: true
- * schema:
- * type: integer
- * responses:
- * 200:
- * description: Search results
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * results:
- * type: array
- * items:
- * $ref: '#/components/schemas/Organization'
- * totalCount:
- * type: integer
- */
-
-/**
- * @swagger
- * /api/organizations/{orgId}/login-url:
- * get:
- * tags: [Organizations]
- * summary: Get organization login URL
- * description: Get OAuth login URL for organization
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: orgId
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Login URL
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * loginUrl:
- * type: string
- */
-
-/**
- * @swagger
- * /api/organizations/auth-callback:
- * post:
- * tags: [Organizations]
- * summary: OAuth callback
- * description: Handle OAuth callback from organization
- * security:
- * - bearerAuth: []
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * code:
- * type: string
- * state:
- * type: string
- * responses:
- * 200:
- * description: Authentication successful
- * 400:
- * description: Invalid callback data
- */
-
-/**
- * @swagger
- * /api/decks/page/{from}/{to}:
- * get:
- * tags: [Decks]
- * summary: Get decks by page
- * description: Retrieve paginated list of decks
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: from
- * in: path
- * required: true
- * schema:
- * type: integer
- * - name: to
- * in: path
- * required: true
- * schema:
- * type: integer
- * responses:
- * 200:
- * description: Paginated decks
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * decks:
- * type: array
- * items:
- * $ref: '#/components/schemas/Deck'
- * totalCount:
- * type: integer
- */
-
-/**
- * @swagger
- * /api/decks/search:
- * get:
- * tags: [Decks]
- * summary: Search decks
- * description: Search decks by query
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: query
- * in: query
- * required: true
- * schema:
- * type: string
- * - name: from
- * in: query
- * required: true
- * schema:
- * type: integer
- * - name: to
- * in: query
- * required: true
- * schema:
- * type: integer
- * responses:
- * 200:
- * description: Search results
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * results:
- * type: array
- * items:
- * $ref: '#/components/schemas/Deck'
- * totalCount:
- * type: integer
- */
-
-/**
- * @swagger
- * /api/decks/{id}:
- * get:
- * tags: [Decks]
- * summary: Get deck by ID
- * description: Retrieve a specific deck by ID
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Deck details
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Deck'
- * 404:
- * description: Deck not found
- * put:
- * tags: [Decks]
- * summary: Update deck
- * description: Update an existing deck
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/CreateDeckRequest'
- * responses:
- * 200:
- * description: Deck updated successfully
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Deck'
- * delete:
- * tags: [Decks]
- * summary: Delete deck
- * description: Delete a deck (soft delete)
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 204:
- * description: Deck deleted successfully
- * 404:
- * description: Deck not found
- */
-
-/**
- * @swagger
- * /api/chats/user-chats:
- * get:
- * tags: [Chats]
- * summary: Get user chats
- * description: Get all chats for the current user
- * security:
- * - bearerAuth: []
- * responses:
- * 200:
- * description: User chats
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: '#/components/schemas/Chat'
- */
-
-/**
- * @swagger
- * /api/chats/history/{chatId}:
- * get:
- * tags: [Chats]
- * summary: Get chat history
- * description: Get message history for a chat
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: chatId
- * in: path
- * required: true
- * schema:
- * type: string
- * - name: page
- * in: query
- * schema:
- * type: integer
- * - name: limit
- * in: query
- * schema:
- * type: integer
- * responses:
- * 200:
- * description: Chat history
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: '#/components/schemas/ChatMessage'
- */
-
-/**
- * @swagger
- * /api/chats/message:
- * post:
- * tags: [Chats]
- * summary: Send message
- * description: Send a message to a chat
- * security:
- * - bearerAuth: []
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * type: object
- * required:
- * - chatId
- * - message
- * properties:
- * chatId:
- * type: string
- * message:
- * type: string
- * responses:
- * 201:
- * description: Message sent successfully
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/ChatMessage'
- */
-
-/**
- * @swagger
- * /api/chats/archive/{chatId}:
- * post:
- * tags: [Chats]
- * summary: Archive chat
- * description: Archive a chat room
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: chatId
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Chat archived successfully
- * 404:
- * description: Chat not found
- */
-
-/**
- * @swagger
- * /api/chats/restore/{chatId}:
- * post:
- * tags: [Chats]
- * summary: Restore chat
- * description: Restore an archived chat room
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: chatId
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Chat restored successfully
- * 404:
- * description: Chat not found
- */
-
-/**
- * @swagger
- * /api/contact/create:
- * post:
- * tags: [Contact]
- * summary: Create contact message
- * description: Send a contact message to the system
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * type: object
- * required:
- * - name
- * - email
- * - message
- * properties:
- * name:
- * type: string
- * email:
- * type: string
- * format: email
- * subject:
- * type: string
- * nullable: true
- * message:
- * type: string
- * responses:
- * 201:
- * description: Contact message sent successfully
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Contact'
- */
-
-/**
- * @swagger
- * /api/admin/users:
- * get:
- * tags: [Admin - Users]
- * summary: Get all users (Admin)
- * description: Retrieve all users in the system with pagination
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: page
- * in: query
- * schema:
- * type: integer
- * default: 1
- * - name: limit
- * in: query
- * schema:
- * type: integer
- * default: 10
- * - name: search
- * in: query
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Users retrieved successfully
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * users:
- * type: array
- * items:
- * $ref: '#/components/schemas/User'
- * total:
- * type: integer
- * page:
- * type: integer
- * limit:
- * type: integer
- */
-
-/**
- * @swagger
- * /api/admin/users/{id}:
- * get:
- * tags: [Admin - Users]
- * summary: Get user by ID (Admin)
- * description: Get detailed information about a specific user
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: User found
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/User'
- * 404:
- * description: User not found
- * put:
- * tags: [Admin - Users]
- * summary: Update user (Admin)
- * description: Update user information by admin
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * username:
- * type: string
- * email:
- * type: string
- * format: email
- * firstName:
- * type: string
- * lastName:
- * type: string
- * isActive:
- * type: boolean
- * role:
- * type: string
- * enum: [user, admin, moderator]
- * responses:
- * 200:
- * description: User updated successfully
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/User'
- * delete:
- * tags: [Admin - Users]
- * summary: Delete user (Admin)
- * description: Delete a user from the system
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: User deleted successfully
- * 404:
- * description: User not found
- */
-
-/**
- * @swagger
- * /api/admin/users/{id}/ban:
- * post:
- * tags: [Admin - Users]
- * summary: Ban user (Admin)
- * description: Ban a user from the system
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * requestBody:
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * reason:
- * type: string
- * duration:
- * type: string
- * description: Ban duration in ISO format or 'permanent'
- * responses:
- * 200:
- * description: User banned successfully
- */
-
-/**
- * @swagger
- * /api/admin/users/{id}/unban:
- * post:
- * tags: [Admin - Users]
- * summary: Unban user (Admin)
- * description: Remove ban from a user
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: User unbanned successfully
- */
-
-/**
- * @swagger
- * /api/admin/decks:
- * get:
- * tags: [Admin - Decks]
- * summary: Get all decks (Admin)
- * description: Retrieve all decks in the system with pagination
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: page
- * in: query
- * schema:
- * type: integer
- * default: 1
- * - name: limit
- * in: query
- * schema:
- * type: integer
- * default: 10
- * - name: search
- * in: query
- * schema:
- * type: string
- * - name: status
- * in: query
- * schema:
- * type: string
- * enum: [public, private, reported]
- * responses:
- * 200:
- * description: Decks retrieved successfully
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * decks:
- * type: array
- * items:
- * $ref: '#/components/schemas/Deck'
- * total:
- * type: integer
- * page:
- * type: integer
- * limit:
- * type: integer
- */
-
-/**
- * @swagger
- * /api/admin/decks/{id}:
- * get:
- * tags: [Admin - Decks]
- * summary: Get deck by ID (Admin)
- * description: Get detailed information about a specific deck
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Deck found
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Deck'
- * 404:
- * description: Deck not found
- * put:
- * tags: [Admin - Decks]
- * summary: Update deck (Admin)
- * description: Update deck information by admin
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * name:
- * type: string
- * description:
- * type: string
- * isPublic:
- * type: boolean
- * isActive:
- * type: boolean
- * responses:
- * 200:
- * description: Deck updated successfully
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Deck'
- * delete:
- * tags: [Admin - Decks]
- * summary: Delete deck (Admin)
- * description: Delete a deck from the system
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Deck deleted successfully
- * 404:
- * description: Deck not found
- */
-
-/**
- * @swagger
- * /api/admin/decks/{id}/moderate:
- * post:
- * tags: [Admin - Decks]
- * summary: Moderate deck (Admin)
- * description: Approve or reject a deck for public visibility
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * type: object
- * required:
- * - action
- * properties:
- * action:
- * type: string
- * enum: [approve, reject, flag]
- * reason:
- * type: string
- * responses:
- * 200:
- * description: Deck moderated successfully
- */
-
-/**
- * @swagger
- * /api/admin/organizations:
- * get:
- * tags: [Admin - Organizations]
- * summary: Get all organizations (Admin)
- * description: Retrieve all organizations in the system with pagination
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: page
- * in: query
- * schema:
- * type: integer
- * default: 1
- * - name: limit
- * in: query
- * schema:
- * type: integer
- * default: 10
- * - name: search
- * in: query
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Organizations retrieved successfully
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * organizations:
- * type: array
- * items:
- * $ref: '#/components/schemas/Organization'
- * total:
- * type: integer
- * page:
- * type: integer
- * limit:
- * type: integer
- */
-
-/**
- * @swagger
- * /api/admin/organizations/{id}:
- * get:
- * tags: [Admin - Organizations]
- * summary: Get organization by ID (Admin)
- * description: Get detailed information about a specific organization
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Organization found
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Organization'
- * 404:
- * description: Organization not found
- * put:
- * tags: [Admin - Organizations]
- * summary: Update organization (Admin)
- * description: Update organization information by admin
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * name:
- * type: string
- * description:
- * type: string
- * isActive:
- * type: boolean
- * responses:
- * 200:
- * description: Organization updated successfully
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Organization'
- * delete:
- * tags: [Admin - Organizations]
- * summary: Delete organization (Admin)
- * description: Delete an organization from the system
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Organization deleted successfully
- * 404:
- * description: Organization not found
- */
-
-/**
- * @swagger
- * /api/admin/organizations/{id}/members:
- * get:
- * tags: [Admin - Organizations]
- * summary: Get organization members (Admin)
- * description: Get all members of an organization
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Organization members
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: '#/components/schemas/User'
- */
-
-/**
- * @swagger
- * /api/admin/chats:
- * get:
- * tags: [Admin - Chats]
- * summary: Get all chats (Admin)
- * description: Retrieve all chats in the system with pagination
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: page
- * in: query
- * schema:
- * type: integer
- * default: 1
- * - name: limit
- * in: query
- * schema:
- * type: integer
- * default: 10
- * - name: search
- * in: query
- * schema:
- * type: string
- * - name: status
- * in: query
- * schema:
- * type: string
- * enum: [active, archived, reported]
- * responses:
- * 200:
- * description: Chats retrieved successfully
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * chats:
- * type: array
- * items:
- * $ref: '#/components/schemas/Chat'
- * total:
- * type: integer
- * page:
- * type: integer
- * limit:
- * type: integer
- */
-
-/**
- * @swagger
- * /api/admin/chats/{id}:
- * get:
- * tags: [Admin - Chats]
- * summary: Get chat by ID (Admin)
- * description: Get detailed information about a specific chat
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Chat found
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Chat'
- * 404:
- * description: Chat not found
- * delete:
- * tags: [Admin - Chats]
- * summary: Delete chat (Admin)
- * description: Delete a chat from the system
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Chat deleted successfully
- * 404:
- * description: Chat not found
- */
-
-/**
- * @swagger
- * /api/admin/chats/{id}/messages:
- * get:
- * tags: [Admin - Chats]
- * summary: Get chat messages (Admin)
- * description: Get all messages in a chat
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * - name: page
- * in: query
- * schema:
- * type: integer
- * - name: limit
- * in: query
- * schema:
- * type: integer
- * responses:
- * 200:
- * description: Chat messages
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: '#/components/schemas/ChatMessage'
- */
-
-/**
- * @swagger
- * /api/admin/chats/{id}/moderate:
- * post:
- * tags: [Admin - Chats]
- * summary: Moderate chat (Admin)
- * description: Moderate a chat room (archive, restore, flag)
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * type: object
- * required:
- * - action
- * properties:
- * action:
- * type: string
- * enum: [archive, restore, flag, unflag]
- * reason:
- * type: string
- * responses:
- * 200:
- * description: Chat moderated successfully
- */
-
-/**
- * @swagger
- * /api/admin/contacts:
- * get:
- * tags: [Admin - Contacts]
- * summary: Get all contact messages (Admin)
- * description: Retrieve all contact messages with pagination
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: page
- * in: query
- * schema:
- * type: integer
- * default: 1
- * - name: limit
- * in: query
- * schema:
- * type: integer
- * default: 10
- * - name: status
- * in: query
- * schema:
- * type: string
- * enum: [unread, read, resolved]
- * - name: search
- * in: query
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Contact messages retrieved successfully
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * contacts:
- * type: array
- * items:
- * $ref: '#/components/schemas/Contact'
- * total:
- * type: integer
- * page:
- * type: integer
- * limit:
- * type: integer
- */
-
-/**
- * @swagger
- * /api/admin/contacts/{id}:
- * get:
- * tags: [Admin - Contacts]
- * summary: Get contact message by ID (Admin)
- * description: Get detailed information about a specific contact message
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Contact message found
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Contact'
- * 404:
- * description: Contact message not found
- * put:
- * tags: [Admin - Contacts]
- * summary: Update contact message status (Admin)
- * description: Update the status of a contact message
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * status:
- * type: string
- * enum: [unread, read, resolved]
- * adminNotes:
- * type: string
- * responses:
- * 200:
- * description: Contact message updated successfully
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Contact'
- * delete:
- * tags: [Admin - Contacts]
- * summary: Delete contact message (Admin)
- * description: Delete a contact message from the system
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Contact message deleted successfully
- * 404:
- * description: Contact message not found
- */
-
-/**
- * @swagger
- * /api/admin/contacts/{id}/reply:
- * post:
- * tags: [Admin - Contacts]
- * summary: Reply to contact message (Admin)
- * description: Send a reply to a contact message
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * type: object
- * required:
- * - reply
- * properties:
- * reply:
- * type: string
- * responses:
- * 200:
- * description: Reply sent successfully
- */
-
-/**
- * @swagger
- * /api/admin/games:
- * get:
- * tags: [Admin - Games]
- * summary: Get all games (Admin)
- * description: Retrieve all games in the system with pagination
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: page
- * in: query
- * schema:
- * type: integer
- * default: 1
- * - name: limit
- * in: query
- * schema:
- * type: integer
- * default: 10
- * - name: status
- * in: query
- * schema:
- * type: string
- * enum: [active, completed, abandoned]
- * responses:
- * 200:
- * description: Games retrieved successfully
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * games:
- * type: array
- * items:
- * $ref: '#/components/schemas/Game'
- * total:
- * type: integer
- * page:
- * type: integer
- * limit:
- * type: integer
- */
-
-/**
- * @swagger
- * /api/admin/games/{id}:
- * get:
- * tags: [Admin - Games]
- * summary: Get game by ID (Admin)
- * description: Get detailed information about a specific game
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Game found
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Game'
- * 404:
- * description: Game not found
- * delete:
- * tags: [Admin - Games]
- * summary: Delete game (Admin)
- * description: Delete a game from the system
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Game deleted successfully
- * 404:
- * description: Game not found
- */
-
-/**
- * @swagger
- * /api/admin/system/stats:
- * get:
- * tags: [Admin - System]
- * summary: Get system statistics (Admin)
- * description: Get comprehensive system statistics
- * security:
- * - bearerAuth: []
- * responses:
- * 200:
- * description: System statistics
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * uptime:
- * type: string
- * version:
- * type: string
- * memoryUsage:
- * type: object
- * activeConnections:
- * type: integer
- * databaseHealth:
- * type: string
- * redisHealth:
- * type: string
- */
-
-/**
- * @swagger
- * /api/admin/system/logs:
- * get:
- * tags: [Admin - System]
- * summary: Get system logs (Admin)
- * description: Retrieve system logs with filtering
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: level
- * in: query
- * schema:
- * type: string
- * enum: [error, warn, info, debug]
- * - name: limit
- * in: query
- * schema:
- * type: integer
- * default: 100
- * - name: since
- * in: query
- * schema:
- * type: string
- * format: date-time
- * responses:
- * 200:
- * description: System logs
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * type: object
- * properties:
- * timestamp:
- * type: string
- * level:
- * type: string
- * message:
- * type: string
- * metadata:
- * type: object
- */
-
-/**
- * @swagger
- * /api/health:
- * get:
- * tags: [System]
- * summary: Health check
- * description: Check the health status of the API
- * responses:
- * 200:
- * description: Service is healthy
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * status:
- * type: string
- * example: "OK"
- * timestamp:
- * type: string
- * format: date-time
- * version:
- * type: string
- */
-
-/**
- * @swagger
- * components:
- * securitySchemes:
- * bearerAuth:
- * type: http
- * scheme: bearer
- * schemas:
- * User:
- * type: object
- * properties:
- * id:
- * type: string
- * format: uuid
- * username:
- * type: string
- * email:
- * type: string
- * format: email
- * fname:
- * type: string
- * lname:
- * type: string
- * phone:
- * type: string
- * nullable: true
- * type:
- * type: string
- * state:
- * type: integer
- * regdate:
- * type: string
- * format: date-time
- * updatedate:
- * type: string
- * format: date-time
- * orgid:
- * type: string
- * nullable: true
- * Deck:
- * type: object
- * properties:
- * id:
- * type: string
- * format: uuid
- * name:
- * type: string
- * type:
- * type: integer
- * userid:
- * type: string
- * format: uuid
- * creationdate:
- * type: string
- * format: date-time
- * cards:
- * type: array
- * items:
- * type: object
- * Organization:
- * type: object
- * properties:
- * id:
- * type: string
- * format: uuid
- * name:
- * type: string
- * description:
- * type: string
- * members:
- * type: array
- * items:
- * $ref: '#/components/schemas/User'
- * Contact:
- * type: object
- * properties:
- * id:
- * type: string
- * format: uuid
- * name:
- * type: string
- * email:
- * type: string
- * format: email
- * type:
- * type: integer
- * txt:
- * type: string
- * userid:
- * type: string
- * nullable: true
- * createdate:
- * type: string
- * format: date-time
- * Chat:
- * type: object
- * properties:
- * id:
- * type: string
- * format: uuid
- * name:
- * type: string
- * gameId:
- * type: string
- * format: uuid
- * messages:
- * type: array
- * items:
- * $ref: '#/components/schemas/ChatMessage'
- * ChatMessage:
- * type: object
- * properties:
- * id:
- * type: string
- * format: uuid
- * chatId:
- * type: string
- * format: uuid
- * senderId:
- * type: string
- * format: uuid
- * message:
- * type: string
- * timestamp:
- * type: string
- * format: date-time
- * Game:
- * type: object
- * properties:
- * id:
- * type: string
- * format: uuid
- * deckids:
- * type: array
- * items:
- * type: string
- * maxplayers:
- * type: integer
- * logintype:
- * type: string
- * state:
- * type: string
- * createdate:
- * type: string
- * format: date-time
- */
-
-/**
- * @swagger
- * tags:
- * - name: Users
- * - name: Decks
- * - name: Organizations
- * - name: Contact
- * - name: Chats
- * - name: Games
- * - name: Admin - Users
- * - name: Admin - Decks
- * - name: Admin - Organizations
- * - name: Admin - Contacts
- * - name: Admin - Chats
- * - name: Admin - Games
- * - name: System
- */
-
-// User endpoints
-/**
- * @swagger
- * /api/users/login:
- * post:
- * tags: [Users]
- * summary: User login
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * type: object
- * required: [username, password]
- * properties:
- * username:
- * type: string
- * password:
- * type: string
- * responses:
- * 200:
- * description: Login successful
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * token:
- * type: string
- */
-
-/**
- * @swagger
- * /api/users/create:
- * post:
- * tags: [Users]
- * summary: Create user
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * type: object
- * required: [username, email, password]
- * properties:
- * username:
- * type: string
- * email:
- * type: string
- * password:
- * type: string
- * responses:
- * 201:
- * description: User created
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/User'
- */
-
-// ...existing code...
-/**
- * @swagger
- * /api/decks/page/{from}/{to}:
- * get:
- * tags: [Decks]
- * summary: Get decks with pagination
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: from
- * in: path
- * required: true
- * schema:
- * type: integer
- * - name: to
- * in: path
- * required: true
- * schema:
- * type: integer
- * responses:
- * 200:
- * description: Paginated decks
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: '#/components/schemas/Deck'
- */
-
-/**
- * @swagger
- * /api/decks/search:
- * get:
- * tags: [Decks]
- * summary: Search decks
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: q
- * in: query
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Search results
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: '#/components/schemas/Deck'
- */
-
-/**
- * @swagger
- * /api/decks/{id}:
- * get:
- * tags: [Decks]
- * summary: Get deck by ID
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: id
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Deck found
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Deck'
- * 404:
- * description: Deck not found
- */
-
-/**
- * @swagger
- * /api/organizations/page/{from}/{to}:
- * get:
- * tags: [Organizations]
- * summary: Get organizations with pagination
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: from
- * in: path
- * required: true
- * schema:
- * type: integer
- * - name: to
- * in: path
- * required: true
- * schema:
- * type: integer
- * responses:
- * 200:
- * description: Paginated organizations
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: '#/components/schemas/Organization'
- */
-
-/**
- * @swagger
- * /api/organizations/search:
- * get:
- * tags: [Organizations]
- * summary: Search organizations
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: q
- * in: query
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Search results
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: '#/components/schemas/Organization'
- */
-
-/**
- * @swagger
- * /api/contact/create:
- * post:
- * tags: [Contact]
- * summary: Create contact message
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * type: object
- * required: [name, email, txt]
- * properties:
- * name:
- * type: string
- * email:
- * type: string
- * format: email
- * txt:
- * type: string
- * responses:
- * 201:
- * description: Contact created
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Contact'
- */
-
-/**
- * @swagger
- * /api/chats/create:
- * post:
- * tags: [Chats]
- * summary: Create chat
- * security:
- * - bearerAuth: []
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * type: object
- * required: [name, gameId]
- * properties:
- * name:
- * type: string
- * gameId:
- * type: string
- * responses:
- * 201:
- * description: Chat created
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Chat'
- */
-
-/**
- * @swagger
- * /api/chats/history/{chatId}:
- * get:
- * tags: [Chats]
- * summary: Get chat history
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: chatId
- * in: path
- * required: true
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Chat history
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: '#/components/schemas/ChatMessage'
- */
-
-/**
- * @swagger
- * /api/games/start:
- * post:
- * tags: [Games]
- * summary: Start a new game
- * security:
- * - bearerAuth: []
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * type: object
- * required: [deckids, maxplayers, logintype]
- * properties:
- * deckids:
- * type: array
- * items:
- * type: string
- * maxplayers:
- * type: integer
- * logintype:
- * type: string
- * responses:
- * 201:
- * description: Game started
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Game'
- */
-
-/**
- * @swagger
- * /api/games/join:
- * post:
- * tags: [Games]
- * summary: Join a game
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * type: object
- * required: [gameId]
- * properties:
- * gameId:
- * type: string
- * responses:
- * 200:
- * description: Joined game
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Game'
- */
-
-// Admin endpoints (examples)
-/**
- * @swagger
- * /api/admin/users:
- * get:
- * tags: [Admin - Users]
- * summary: Get all users (Admin)
- * security:
- * - bearerAuth: []
- * responses:
- * 200:
- * description: Users retrieved
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: '#/components/schemas/User'
- */
-
-/**
- * @swagger
- * /api/admin/decks:
- * get:
- * tags: [Admin - Decks]
- * summary: Get all decks (Admin)
- * security:
- * - bearerAuth: []
- * responses:
- * 200:
- * description: Decks retrieved
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: '#/components/schemas/Deck'
- */
-
-/**
- * @swagger
- * /api/admin/organizations:
- * get:
- * tags: [Admin - Organizations]
- * summary: Get all organizations (Admin)
- * security:
- * - bearerAuth: []
- * responses:
- * 200:
- * description: Organizations retrieved
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: '#/components/schemas/Organization'
- */
-
-/**
- * @swagger
- * /api/admin/contacts:
- * get:
- * tags: [Admin - Contacts]
- * summary: Get all contact messages (Admin)
- * security:
- * - bearerAuth: []
- * responses:
- * 200:
- * description: Contacts retrieved
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: '#/components/schemas/Contact'
- */
-
-/**
- * @swagger
- * /api/admin/chats:
- * get:
- * tags: [Admin - Chats]
- * summary: Get all chats (Admin)
- * security:
- * - bearerAuth: []
- * responses:
- * 200:
- * description: Chats retrieved
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: '#/components/schemas/Chat'
- */
-
-/**
- * @swagger
- * /api/admin/games:
- * get:
- * tags: [Admin - Games]
- * summary: Get all games (Admin)
- * security:
- * - bearerAuth: []
- * responses:
- * 200:
- * description: Games retrieved
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: '#/components/schemas/Game'
- */
-
-/**
- * @swagger
- * /api/contacts:
- * post:
- * tags: [Contacts]
- * summary: Create contact
- * description: Create a new contact message
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * type: object
- * required:
- * - name
- * - email
- * - type
- * - txt
- * properties:
- * name:
- * type: string
- * email:
- * type: string
- * format: email
- * type:
- * type: integer
- * enum: [0, 1, 2]
- * description: 0=QUESTION, 1=BUG_REPORT, 2=SUGGESTION
- * txt:
- * type: string
- * responses:
- * 201:
- * description: Contact created successfully
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Contact'
- */
-
-/**
- * @swagger
- * /api/deck-import-export/export/{deckId}:
- * get:
- * tags: [Deck Import/Export]
- * summary: Export deck
- * description: Export a deck as JSON or .spr file
- * security:
- * - bearerAuth: []
- * parameters:
- * - name: deckId
- * in: path
- * required: true
- * schema:
- * type: string
- * - name: format
- * in: query
- * schema:
- * type: string
- * enum: [json, spr]
- * default: json
- * responses:
- * 200:
- * description: Deck exported successfully
- * content:
- * application/json:
- * schema:
- * type: object
- * application/octet-stream:
- * schema:
- * type: string
- * format: binary
- */
-
-/**
- * @swagger
- * /api/deck-import-export/import:
- * post:
- * tags: [Deck Import/Export]
- * summary: Import deck
- * description: Import a deck from JSON or .spr file
- * security:
- * - bearerAuth: []
- * requestBody:
- * required: true
- * content:
- * multipart/form-data:
- * schema:
- * type: object
- * properties:
- * file:
- * type: string
- * format: binary
- * responses:
- * 201:
- * description: Deck imported successfully
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Deck'
- */
-
-/**
- * @swagger
- * /api/games/start:
- * post:
- * summary: Start a new game
- * tags: [Games]
- * security:
- * - bearerAuth: []
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * type: object
- * required:
- * - deckids
- * - maxplayers
- * - logintype
- * properties:
- * deckids:
- * type: array
- * items:
- * type: string
- * description: Array of deck IDs (must include all 3 types LUCK, JOKER, QUESTION)
- * maxplayers:
- * type: integer
- * minimum: 2
- * maximum: 8
- * description: Maximum number of players allowed in the game
- * logintype:
- * type: integer
- * enum: [0, 1, 2]
- * description: How players can join (PUBLIC=0, PRIVATE=1, ORGANIZATION=2)
- * responses:
- * 200:
- * description: Game started successfully
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Game'
- * 400:
- * description: Invalid input parameters
- * 401:
- * description: Authentication required
- * 500:
- * description: Internal server error
- */
-
-/**
- * @swagger
- * /api/games/join:
- * post:
- * summary: Join a game (automatically detects game type)
- * description: Join any game by providing the game code. The system automatically determines if authentication is required based on the game type.
- * tags: [Games]
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * type: object
- * required:
- * - gameCode
- * properties:
- * gameCode:
- * type: string
- * description: 6-character game code
- * example: "ABC123"
- * playerName:
- * type: string
- * description: Display name for the player (required for public games, optional for authenticated games)
- * example: "John Doe"
- * responses:
- * 200:
- * description: Successfully joined the game
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/Game'
- * 400:
- * description: Invalid input or missing required fields
- * 401:
- * description: Authentication required for this game type
- * 403:
- * description: Organization membership required
- * 404:
- * description: Game not found
- * 409:
- * description: Game is full or not accepting players
- * 500:
- * description: Internal server error
- */
-
-/**
- * @swagger
- * /api/games/{gameId}/start:
- * post:
- * summary: Start gameplay for an existing game
- * description: Initialize gameplay by setting all player positions to 0 and assigning random turn order. This is separate from game creation.
- * tags: [Games]
- * parameters:
- * - in: path
- * name: gameId
- * required: true
- * schema:
- * type: string
- * description: The ID of the game to start
- * responses:
- * 200:
- * description: Game started successfully
- * content:
- * application/json:
- * schema:
- * type: object
- * properties:
- * message:
- * type: string
- * example: "Game started successfully"
- * gameId:
- * type: string
- * example: "game123"
- * playerCount:
- * type: number
- * example: 4
- * 400:
- * description: Invalid input or game cannot be started
- * 401:
- * description: Authentication required
- * 403:
- * description: Only game master can start the game
- * 404:
- * description: Game not found
- * 409:
- * description: Game already started or not ready to start
- * 500:
- * description: Internal server error
- */
-
-export {};
\ No newline at end of file
diff --git a/SerpentRace_Backend/src/Api/swagger/swaggerUiSetup.ts b/SerpentRace_Backend/src/Api/swagger/swaggerUiSetup.ts
deleted file mode 100644
index f474fe87..00000000
--- a/SerpentRace_Backend/src/Api/swagger/swaggerUiSetup.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import express from 'express';
-import swaggerUi from 'swagger-ui-express';
-import { swaggerSpec } from './swaggerConfig';
-
-export function setupSwagger(app: express.Application) {
- app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec));
-}
diff --git a/SerpentRace_Backend/src/Application/Chat/commands/ChatArchiveCommandHandlers.ts b/SerpentRace_Backend/src/Application/Chat/commands/ChatArchiveCommandHandlers.ts
deleted file mode 100644
index c9456564..00000000
--- a/SerpentRace_Backend/src/Application/Chat/commands/ChatArchiveCommandHandlers.ts
+++ /dev/null
@@ -1,69 +0,0 @@
-import { ArchiveChatCommand, RestoreChatCommand } from './ChatCommands';
-import { IChatRepository } from '../../../Domain/IRepository/IChatRepository';
-import { ChatType } from '../../../Domain/Chat/ChatAggregate';
-import { logAuth, logError, logWarning } from '../../Services/Logger';
-
-export class ArchiveChatCommandHandler {
- constructor(private chatRepository: IChatRepository) {}
-
- async execute(command: ArchiveChatCommand): Promise {
- try {
- const chat = await this.chatRepository.findById(command.chatId);
- if (!chat) {
- throw new Error('Chat not found');
- }
-
- await this.chatRepository.archiveChat(chat);
-
- logAuth('Chat archived manually', undefined, {
- chatId: command.chatId,
- chatType: chat.type,
- messageCount: chat.messages.length
- });
-
- return true;
-
- } catch (error) {
- logError('ArchiveChatCommandHandler error', error as Error);
- return false;
- }
- }
-}
-
-export class RestoreChatCommandHandler {
- constructor(private chatRepository: IChatRepository) {}
-
- async execute(command: RestoreChatCommand): Promise {
- try {
- const archive = await this.chatRepository.getArchivedChat(command.chatId);
- if (!archive) {
- throw new Error('Archived chat not found');
- }
-
- // Game chats cannot be restored, only viewed
- if (archive.chatType === ChatType.GAME) {
- logWarning('Attempt to restore game chat blocked', {
- chatId: command.chatId,
- chatType: archive.chatType
- });
- return false;
- }
-
- const restoredChat = await this.chatRepository.restoreFromArchive(command.chatId);
- if (!restoredChat) {
- throw new Error('Failed to restore chat from archive');
- }
-
- logAuth('Chat restored from archive', undefined, {
- chatId: command.chatId,
- messageCount: archive.archivedMessages.length
- });
-
- return true;
-
- } catch (error) {
- logError('RestoreChatCommandHandler error', error as Error);
- return false;
- }
- }
-}
diff --git a/SerpentRace_Backend/src/Application/Chat/commands/ChatCommands.ts b/SerpentRace_Backend/src/Application/Chat/commands/ChatCommands.ts
deleted file mode 100644
index 41d2bb47..00000000
--- a/SerpentRace_Backend/src/Application/Chat/commands/ChatCommands.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-export interface CreateChatCommand {
- type: 'direct' | 'group' | 'game';
- name?: string;
- gameId?: string;
- createdBy: string;
- userIds: string[];
-}
-
-export interface SendMessageCommand {
- chatId: string;
- userId: string;
- message: string;
-}
-
-export interface ArchiveChatCommand {
- chatId: string;
-}
-
-export interface RestoreChatCommand {
- chatId: string;
-}
diff --git a/SerpentRace_Backend/src/Application/Chat/commands/CreateChatCommandHandler.ts b/SerpentRace_Backend/src/Application/Chat/commands/CreateChatCommandHandler.ts
deleted file mode 100644
index d007c28b..00000000
--- a/SerpentRace_Backend/src/Application/Chat/commands/CreateChatCommandHandler.ts
+++ /dev/null
@@ -1,85 +0,0 @@
-import { CreateChatCommand } from './ChatCommands';
-import { IChatRepository } from '../../../Domain/IRepository/IChatRepository';
-import { IUserRepository } from '../../../Domain/IRepository/IUserRepository';
-import { ChatType, ChatAggregate } from '../../../Domain/Chat/ChatAggregate';
-import { UserState } from '../../../Domain/User/UserAggregate';
-import { logAuth, logError } from '../../Services/Logger';
-
-export class CreateChatCommandHandler {
- constructor(
- private chatRepository: IChatRepository,
- private userRepository: IUserRepository
- ) {}
-
- async execute(command: CreateChatCommand): Promise {
- try {
- // Validate creator exists
- const creator = await this.userRepository.findById(command.createdBy);
- if (!creator) {
- throw new Error('Creator not found');
- }
-
- // For group chats, check if creator is premium
- if (command.type === 'group' && creator.state !== UserState.VERIFIED_PREMIUM) {
- throw new Error('Premium subscription required to create groups');
- }
-
- // Validate all target users exist
- const targetUsers = await Promise.all(
- command.userIds.map(id => this.userRepository.findById(id))
- );
-
- if (targetUsers.some(user => !user)) {
- throw new Error('One or more target users not found');
- }
-
- // For direct chats, check if already exists
- if (command.type === 'direct' && command.userIds.length === 1) {
- const existingChats = await this.chatRepository.findByUserId(command.createdBy);
- const existingDirectChat = existingChats.find(chat =>
- chat.type === ChatType.DIRECT &&
- chat.users.length === 2 &&
- chat.users.includes(command.userIds[0])
- );
-
- if (existingDirectChat) {
- return existingDirectChat;
- }
- }
-
- // For game chats, check if already exists
- if (command.type === 'game' && command.gameId) {
- const existingGameChat = await this.chatRepository.findByGameId(command.gameId);
- if (existingGameChat) {
- return existingGameChat;
- }
- }
-
- // Create chat
- const chatData: Partial = {
- type: command.type as any,
- name: command.name,
- gameId: command.gameId,
- createdBy: command.createdBy,
- users: [command.createdBy, ...command.userIds],
- messages: [],
- lastActivity: new Date()
- };
-
- const chat = await this.chatRepository.create(chatData);
-
- logAuth('Chat created successfully', command.createdBy, {
- chatId: chat.id,
- chatType: command.type,
- participantCount: chat.users.length,
- gameId: command.gameId
- });
-
- return chat;
-
- } catch (error) {
- logError('CreateChatCommandHandler error', error as Error);
- return null;
- }
- }
-}
diff --git a/SerpentRace_Backend/src/Application/Chat/commands/SendMessageCommandHandler.ts b/SerpentRace_Backend/src/Application/Chat/commands/SendMessageCommandHandler.ts
deleted file mode 100644
index 8bd6903a..00000000
--- a/SerpentRace_Backend/src/Application/Chat/commands/SendMessageCommandHandler.ts
+++ /dev/null
@@ -1,84 +0,0 @@
-import { SendMessageCommand } from './ChatCommands';
-import { IChatRepository } from '../../../Domain/IRepository/IChatRepository';
-import { Message } from '../../../Domain/Chat/ChatAggregate';
-import { logAuth, logError } from '../../Services/Logger';
-import { v4 as uuidv4 } from 'uuid';
-
-export class SendMessageCommandHandler {
- constructor(private chatRepository: IChatRepository) {}
-
- async execute(command: SendMessageCommand): Promise {
- try {
- // Validate message is non-empty string
- if (typeof command.message !== 'string' || !command.message.trim()) {
- throw new Error('Message must be a non-empty string');
- }
-
- const chat = await this.chatRepository.findById(command.chatId);
- if (!chat) {
- throw new Error('Chat not found');
- }
-
- // Check if user is member of this chat
- if (!chat.users.includes(command.userId)) {
- throw new Error('User is not a member of this chat');
- }
-
- // Create message
- const message: Message = {
- id: uuidv4(),
- date: new Date(),
- userid: command.userId,
- text: command.message.trim()
- };
-
- // Manage message history (keep last 10 per user, up to 2 weeks)
- let updatedMessages = [...chat.messages, message];
- updatedMessages = this.pruneMessages(updatedMessages);
-
- // Update chat
- await this.chatRepository.update(command.chatId, {
- messages: updatedMessages,
- lastActivity: new Date()
- });
-
- logAuth('Message sent successfully', command.userId, {
- chatId: command.chatId,
- messageLength: command.message.length,
- totalMessages: updatedMessages.length
- });
-
- return message;
-
- } catch (error) {
- logError('SendMessageCommandHandler error', error as Error);
- return null;
- }
- }
-
- private pruneMessages(messages: Message[]): Message[] {
- const twoWeeksAgo = new Date(Date.now() - 14 * 24 * 60 * 60 * 1000);
-
- // Remove messages older than 2 weeks
- let prunedMessages = messages.filter(msg => new Date(msg.date) > twoWeeksAgo);
-
- // Group by user and keep last 10 messages per user
- const messagesByUser = new Map();
- prunedMessages.forEach(msg => {
- if (!messagesByUser.has(msg.userid)) {
- messagesByUser.set(msg.userid, []);
- }
- messagesByUser.get(msg.userid)!.push(msg);
- });
-
- // Keep only last 10 messages per user
- const finalMessages: Message[] = [];
- messagesByUser.forEach((userMessages, userId) => {
- const last10 = userMessages.slice(-10);
- finalMessages.push(...last10);
- });
-
- // Sort by date
- return finalMessages.sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime());
- }
-}
diff --git a/SerpentRace_Backend/src/Application/Chat/commands/SoftDeleteCommandHandlers.ts b/SerpentRace_Backend/src/Application/Chat/commands/SoftDeleteCommandHandlers.ts
deleted file mode 100644
index e69de29b..00000000
diff --git a/SerpentRace_Backend/src/Application/Chat/queries/ChatHistoryQueryHandlers.ts b/SerpentRace_Backend/src/Application/Chat/queries/ChatHistoryQueryHandlers.ts
deleted file mode 100644
index 5f215037..00000000
--- a/SerpentRace_Backend/src/Application/Chat/queries/ChatHistoryQueryHandlers.ts
+++ /dev/null
@@ -1,141 +0,0 @@
-import { GetChatHistoryQuery, GetArchivedChatsQuery } from './ChatQueries';
-import { IChatRepository } from '../../../Domain/IRepository/IChatRepository';
-import { IChatArchiveRepository } from '../../../Domain/IRepository/IChatArchiveRepository';
-import { Message } from '../../../Domain/Chat/ChatAggregate';
-import { logAuth, logError, logWarning } from '../../Services/Logger';
-
-interface ChatHistoryResult {
- chatId: string;
- messages: Message[];
- isArchived: boolean;
- chatInfo: {
- type: string;
- name: string | null;
- gameId: string | null;
- users: string[];
- };
-}
-
-export class GetChatHistoryQueryHandler {
- constructor(
- private chatRepository: IChatRepository,
- private chatArchiveRepository: IChatArchiveRepository
- ) {}
-
- async execute(query: GetChatHistoryQuery): Promise {
- try {
- // First try to find active chat
- const chat = await this.chatRepository.findById(query.chatId);
-
- if (chat) {
- // Check authorization
- if (!chat.users.includes(query.userId)) {
- logWarning('Unauthorized chat history access attempt', {
- chatId: query.chatId,
- userId: query.userId
- });
- return null;
- }
-
- logAuth('Chat history retrieved', query.userId, {
- chatId: query.chatId,
- messageCount: chat.messages.length,
- isArchived: false
- });
-
- return {
- chatId: query.chatId,
- messages: chat.messages,
- isArchived: false,
- chatInfo: {
- type: chat.type,
- name: chat.name,
- gameId: chat.gameId,
- users: chat.users
- }
- };
- }
-
- // Try to find in archives
- const archives = await this.chatArchiveRepository.findByChatId(query.chatId);
- const userArchive = archives.find(archive =>
- archive.participants.includes(query.userId)
- );
-
- if (userArchive) {
- logAuth('Archived chat history retrieved', query.userId, {
- chatId: query.chatId,
- messageCount: userArchive.archivedMessages.length,
- isArchived: true
- });
-
- return {
- chatId: query.chatId,
- messages: userArchive.archivedMessages,
- isArchived: true,
- chatInfo: {
- type: userArchive.chatType,
- name: userArchive.chatName,
- gameId: userArchive.gameId,
- users: userArchive.participants
- }
- };
- }
-
- logWarning('Chat history not found', {
- chatId: query.chatId,
- userId: query.userId
- });
-
- return null;
-
- } catch (error) {
- logError('GetChatHistoryQueryHandler error', error as Error);
- return null;
- }
- }
-}
-
-export class GetArchivedChatsQueryHandler {
- constructor(private chatArchiveRepository: IChatArchiveRepository) {}
-
- async execute(query: GetArchivedChatsQuery): Promise {
- try {
- let archives: any[] = [];
-
- if (query.gameId) {
- // Get archived game chats
- archives = await this.chatArchiveRepository.findByGameId(query.gameId);
- } else {
- // Get all archived chats for user (would need different query)
- // For now, return empty - this would need a new repository method
- archives = [];
- }
-
- const result = archives
- .filter(archive => archive.participants.includes(query.userId))
- .map(archive => ({
- chatId: archive.chatId,
- messages: archive.archivedMessages,
- isArchived: true,
- chatInfo: {
- type: archive.chatType,
- name: archive.chatName,
- gameId: archive.gameId,
- users: archive.participants
- }
- }));
-
- logAuth('Archived chats retrieved', query.userId, {
- count: result.length,
- gameId: query.gameId
- });
-
- return result;
-
- } catch (error) {
- logError('GetArchivedChatsQueryHandler error', error as Error);
- return [];
- }
- }
-}
diff --git a/SerpentRace_Backend/src/Application/Chat/queries/ChatQueries.ts b/SerpentRace_Backend/src/Application/Chat/queries/ChatQueries.ts
deleted file mode 100644
index 69e0b36c..00000000
--- a/SerpentRace_Backend/src/Application/Chat/queries/ChatQueries.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-export interface GetUserChatsQuery {
- userId: string;
- includeArchived?: boolean;
-}
-
-export interface GetChatHistoryQuery {
- chatId: string;
- userId: string; // For authorization
-}
-
-export interface GetArchivedChatsQuery {
- userId: string;
- gameId?: string;
-}
diff --git a/SerpentRace_Backend/src/Application/Chat/queries/GetChatsByPageQuery.ts b/SerpentRace_Backend/src/Application/Chat/queries/GetChatsByPageQuery.ts
deleted file mode 100644
index 18fc595d..00000000
--- a/SerpentRace_Backend/src/Application/Chat/queries/GetChatsByPageQuery.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export interface GetChatsByPageQuery {
- from: number;
- to: number;
- includeDeleted?: boolean;
-}
diff --git a/SerpentRace_Backend/src/Application/Chat/queries/GetChatsByPageQueryHandler.ts b/SerpentRace_Backend/src/Application/Chat/queries/GetChatsByPageQueryHandler.ts
deleted file mode 100644
index fbafa33c..00000000
--- a/SerpentRace_Backend/src/Application/Chat/queries/GetChatsByPageQueryHandler.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-import { IChatRepository } from '../../../Domain/IRepository/IChatRepository';
-import { GetChatsByPageQuery } from './GetChatsByPageQuery';
-import { ShortChatDto } from '../../DTOs/ChatDto';
-import { ChatMapper } from '../../DTOs/Mappers/ChatMapper';
-import { logRequest, logError } from '../../Services/Logger';
-
-export class GetChatsByPageQueryHandler {
- constructor(private readonly chatRepo: IChatRepository) {}
-
- async execute(query: GetChatsByPageQuery): Promise<{ chats: ShortChatDto[], totalCount: number }> {
- try {
- // Validate pagination parameters
- if (query.from < 0 || query.to < query.from) {
- throw new Error('Invalid pagination parameters');
- }
-
- const limit = query.to - query.from + 1;
- if (limit > 100) {
- throw new Error('Page size too large. Maximum 100 records per request');
- }
-
- logRequest('Get chats by page query started', undefined, undefined, {
- from: query.from,
- to: query.to,
- includeDeleted: query.includeDeleted || false
- });
-
- const result = query.includeDeleted
- ? await this.chatRepo.findByPageIncludingDeleted(query.from, query.to)
- : await this.chatRepo.findByPage(query.from, query.to);
-
- logRequest('Get chats by page query completed', undefined, undefined, {
- from: query.from,
- to: query.to,
- returned: result.chats.length,
- totalCount: result.totalCount,
- includeDeleted: query.includeDeleted || false
- });
-
- return {
- chats: ChatMapper.toShortDtoList(result.chats),
- totalCount: result.totalCount
- };
- } catch (error) {
- logError('GetChatsByPageQueryHandler error', error instanceof Error ? error : new Error(String(error)));
-
- // Re-throw validation errors as-is
- if (error instanceof Error && (error.message.includes('Invalid pagination') || error.message.includes('Page size'))) {
- throw error;
- }
-
- throw new Error('Failed to retrieve chats page');
- }
- }
-}
diff --git a/SerpentRace_Backend/src/Application/Chat/queries/GetUserChatsQueryHandler.ts b/SerpentRace_Backend/src/Application/Chat/queries/GetUserChatsQueryHandler.ts
deleted file mode 100644
index abb6fad0..00000000
--- a/SerpentRace_Backend/src/Application/Chat/queries/GetUserChatsQueryHandler.ts
+++ /dev/null
@@ -1,97 +0,0 @@
-import { GetUserChatsQuery } from './ChatQueries';
-import { IChatRepository } from '../../../Domain/IRepository/IChatRepository';
-import { IChatArchiveRepository } from '../../../Domain/IRepository/IChatArchiveRepository';
-import { ChatAggregate } from '../../../Domain/Chat/ChatAggregate';
-import { ChatArchiveAggregate } from '../../../Domain/Chat/ChatArchiveAggregate';
-import { logAuth, logError } from '../../Services/Logger';
-
-interface ChatWithMetadata {
- id: string;
- type: string;
- name: string | null;
- gameId: string | null;
- users: string[];
- lastActivity: Date | null;
- isArchived: boolean;
- messageCount: number;
- unreadCount?: number;
-}
-
-export class GetUserChatsQueryHandler {
- constructor(
- private chatRepository: IChatRepository,
- private chatArchiveRepository: IChatArchiveRepository
- ) {}
-
- async execute(query: GetUserChatsQuery): Promise {
- try {
- const result: ChatWithMetadata[] = [];
-
- // Get active chats
- const activeChats = await this.chatRepository.findActiveChatsForUser(query.userId);
- result.push(...activeChats.map(chat => ({
- id: chat.id,
- type: chat.type,
- name: chat.name,
- gameId: chat.gameId,
- users: chat.users,
- lastActivity: chat.lastActivity,
- isArchived: false,
- messageCount: chat.messages.length,
- unreadCount: this.calculateUnreadMessages(chat, query.userId)
- })));
-
- // Get archived chats if requested
- if (query.includeArchived) {
- const userActiveChats = await this.chatRepository.findByUserId(query.userId);
- const archivedChatIds = userActiveChats
- .filter(chat => chat.archiveDate !== null)
- .map(chat => chat.id);
-
- const archives = await Promise.all(
- archivedChatIds.map(id => this.chatArchiveRepository.findByChatId(id))
- );
-
- archives.forEach(archiveArray => {
- archiveArray.forEach(archive => {
- if (archive.participants.includes(query.userId)) {
- result.push({
- id: archive.chatId,
- type: archive.chatType,
- name: archive.chatName,
- gameId: archive.gameId,
- users: archive.participants,
- lastActivity: archive.archivedAt,
- isArchived: true,
- messageCount: archive.archivedMessages.length,
- unreadCount: 0 // Archived chats have no unread messages
- });
- }
- });
- });
- }
-
- logAuth('User chats retrieved', query.userId, {
- activeCount: activeChats.length,
- totalCount: result.length,
- includeArchived: query.includeArchived
- });
-
- return result.sort((a, b) => {
- if (!a.lastActivity) return 1;
- if (!b.lastActivity) return -1;
- return new Date(b.lastActivity).getTime() - new Date(a.lastActivity).getTime();
- });
-
- } catch (error) {
- logError('GetUserChatsQueryHandler error', error as Error);
- return [];
- }
- }
-
- private calculateUnreadMessages(chat: ChatAggregate, userId: string): number {
- // Simple implementation - count messages from other users
- // In production, you'd store lastSeen timestamp per user per chat
- return chat.messages.filter(msg => msg.userid !== userId).length;
- }
-}
diff --git a/SerpentRace_Backend/src/Application/Contact/commands/CreateContactCommand.ts b/SerpentRace_Backend/src/Application/Contact/commands/CreateContactCommand.ts
deleted file mode 100644
index 54ceeee5..00000000
--- a/SerpentRace_Backend/src/Application/Contact/commands/CreateContactCommand.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import { ContactType } from '../../../Domain/Contact/ContactAggregate';
-
-export interface CreateContactCommand {
- name: string;
- email: string;
- userid?: string;
- type: ContactType;
- txt: string;
-}
diff --git a/SerpentRace_Backend/src/Application/Contact/commands/CreateContactCommandHandler.ts b/SerpentRace_Backend/src/Application/Contact/commands/CreateContactCommandHandler.ts
deleted file mode 100644
index ddc2a40b..00000000
--- a/SerpentRace_Backend/src/Application/Contact/commands/CreateContactCommandHandler.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { IContactRepository } from '../../../Domain/IRepository/IContactRepository';
-import { CreateContactCommand } from './CreateContactCommand';
-import { ShortContactDto } from '../../DTOs/ContactDto';
-import { ContactAggregate, ContactState } from '../../../Domain/Contact/ContactAggregate';
-import { ContactMapper } from '../../DTOs/Mappers/ContactMapper';
-
-export class CreateContactCommandHandler {
- constructor(private readonly contactRepo: IContactRepository) {}
-
- async execute(cmd: CreateContactCommand): Promise {
- try {
- const contact = new ContactAggregate();
- contact.name = cmd.name;
- contact.email = cmd.email;
- contact.userid = cmd.userid || null;
- contact.type = cmd.type;
- contact.txt = cmd.txt;
- contact.state = ContactState.ACTIVE;
-
- const created = await this.contactRepo.create(contact);
- return ContactMapper.toShortDto(created);
- } catch (error) {
- throw new Error('Failed to create contact');
- }
- }
-}
diff --git a/SerpentRace_Backend/src/Application/Contact/commands/DeleteContactCommand.ts b/SerpentRace_Backend/src/Application/Contact/commands/DeleteContactCommand.ts
deleted file mode 100644
index 99b1e0b7..00000000
--- a/SerpentRace_Backend/src/Application/Contact/commands/DeleteContactCommand.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface DeleteContactCommand {
- id: string;
- hard?: boolean; // true for permanent delete, false/undefined for soft delete
-}
diff --git a/SerpentRace_Backend/src/Application/Contact/commands/DeleteContactCommandHandler.ts b/SerpentRace_Backend/src/Application/Contact/commands/DeleteContactCommandHandler.ts
deleted file mode 100644
index c2a3f9f9..00000000
--- a/SerpentRace_Backend/src/Application/Contact/commands/DeleteContactCommandHandler.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import { IContactRepository } from '../../../Domain/IRepository/IContactRepository';
-import { DeleteContactCommand } from './DeleteContactCommand';
-import { AdminAuditService } from '../../Services/AdminBypassService';
-import { logRequest } from '../../Services/Logger';
-
-export class DeleteContactCommandHandler {
- constructor(private readonly contactRepo: IContactRepository) {}
-
- async execute(cmd: DeleteContactCommand): Promise {
- try {
- const existingContact = await this.contactRepo.findById(cmd.id);
- if (!existingContact) {
- throw new Error('Contact not found');
- }
-
- if (cmd.hard) {
- // Permanent delete
- await this.contactRepo.delete(cmd.id);
- logRequest('Contact hard deleted', undefined, undefined, {
- contactId: cmd.id,
- contactEmail: existingContact.email,
- deleteType: 'hard'
- });
- } else {
- // Soft delete (default)
- await this.contactRepo.softDelete(cmd.id);
- logRequest('Contact soft deleted', undefined, undefined, {
- contactId: cmd.id,
- contactEmail: existingContact.email,
- deleteType: 'soft'
- });
- }
-
- return true;
- } catch (error) {
- if (error instanceof Error && error.message === 'Contact not found') {
- throw error;
- }
- throw new Error('Failed to delete contact');
- }
- }
-}
diff --git a/SerpentRace_Backend/src/Application/Contact/commands/UpdateContactCommand.ts b/SerpentRace_Backend/src/Application/Contact/commands/UpdateContactCommand.ts
deleted file mode 100644
index 6d66e809..00000000
--- a/SerpentRace_Backend/src/Application/Contact/commands/UpdateContactCommand.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export interface UpdateContactCommand {
- id: string;
- adminResponse?: string;
- state?: number;
- respondedBy?: string;
-}
diff --git a/SerpentRace_Backend/src/Application/Contact/commands/UpdateContactCommandHandler.ts b/SerpentRace_Backend/src/Application/Contact/commands/UpdateContactCommandHandler.ts
deleted file mode 100644
index e25ec319..00000000
--- a/SerpentRace_Backend/src/Application/Contact/commands/UpdateContactCommandHandler.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import { IContactRepository } from '../../../Domain/IRepository/IContactRepository';
-import { UpdateContactCommand } from './UpdateContactCommand';
-import { DetailContactDto } from '../../DTOs/ContactDto';
-import { ContactMapper } from '../../DTOs/Mappers/ContactMapper';
-import { ContactState } from '../../../Domain/Contact/ContactAggregate';
-
-export class UpdateContactCommandHandler {
- constructor(private readonly contactRepo: IContactRepository) {}
-
- async execute(cmd: UpdateContactCommand): Promise {
- try {
- const existingContact = await this.contactRepo.findById(cmd.id);
- if (!existingContact) {
- throw new Error('Contact not found');
- }
-
- const updateData: any = {};
-
- if (cmd.adminResponse !== undefined) {
- updateData.adminResponse = cmd.adminResponse;
- updateData.responseDate = new Date();
- }
-
- if (cmd.state !== undefined) {
- updateData.state = cmd.state;
- }
-
- if (cmd.respondedBy !== undefined) {
- updateData.respondedBy = cmd.respondedBy;
- }
-
- const updated = await this.contactRepo.update(cmd.id, updateData);
- if (!updated) {
- throw new Error('Failed to update contact');
- }
-
- return ContactMapper.toDetailDto(updated);
- } catch (error) {
- if (error instanceof Error && error.message === 'Contact not found') {
- throw error;
- }
- throw new Error('Failed to update contact');
- }
- }
-}
diff --git a/SerpentRace_Backend/src/Application/Contact/queries/GetContactByIdQuery.ts b/SerpentRace_Backend/src/Application/Contact/queries/GetContactByIdQuery.ts
deleted file mode 100644
index f8686379..00000000
--- a/SerpentRace_Backend/src/Application/Contact/queries/GetContactByIdQuery.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export interface GetContactByIdQuery {
- id: string;
-}
diff --git a/SerpentRace_Backend/src/Application/Contact/queries/GetContactByIdQueryHandler.ts b/SerpentRace_Backend/src/Application/Contact/queries/GetContactByIdQueryHandler.ts
deleted file mode 100644
index d20f3c7a..00000000
--- a/SerpentRace_Backend/src/Application/Contact/queries/GetContactByIdQueryHandler.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import { IContactRepository } from '../../../Domain/IRepository/IContactRepository';
-import { GetContactByIdQuery } from './GetContactByIdQuery';
-import { DetailContactDto } from '../../DTOs/ContactDto';
-import { ContactMapper } from '../../DTOs/Mappers/ContactMapper';
-
-export class GetContactByIdQueryHandler {
- constructor(private readonly contactRepo: IContactRepository) {}
-
- async execute(query: GetContactByIdQuery): Promise {
- const contact = await this.contactRepo.findById(query.id);
- if (!contact) {
- return null;
- }
- return ContactMapper.toDetailDto(contact);
- }
-}
diff --git a/SerpentRace_Backend/src/Application/Contact/queries/GetContactsByPageQuery.ts b/SerpentRace_Backend/src/Application/Contact/queries/GetContactsByPageQuery.ts
deleted file mode 100644
index cc5850ab..00000000
--- a/SerpentRace_Backend/src/Application/Contact/queries/GetContactsByPageQuery.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface GetContactsByPageQuery {
- from: number;
- to: number;
-}
diff --git a/SerpentRace_Backend/src/Application/Contact/queries/GetContactsByPageQueryHandler.ts b/SerpentRace_Backend/src/Application/Contact/queries/GetContactsByPageQueryHandler.ts
deleted file mode 100644
index e39234df..00000000
--- a/SerpentRace_Backend/src/Application/Contact/queries/GetContactsByPageQueryHandler.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { IContactRepository } from '../../../Domain/IRepository/IContactRepository';
-import { GetContactsByPageQuery } from './GetContactsByPageQuery';
-import { ContactPageDto } from '../../DTOs/ContactDto';
-import { ContactMapper } from '../../DTOs/Mappers/ContactMapper';
-
-export class GetContactsByPageQueryHandler {
- constructor(private readonly contactRepo: IContactRepository) {}
-
- async execute(query: GetContactsByPageQuery): Promise {
- const result = await this.contactRepo.findByPage(query.from, query.to);
- return {
- contacts: ContactMapper.toShortDtoList(result.contacts),
- totalCount: result.totalCount,
- from: query.from,
- to: query.to,
- };
- }
-}
diff --git a/SerpentRace_Backend/src/Application/DTOs/ChatDto.ts b/SerpentRace_Backend/src/Application/DTOs/ChatDto.ts
deleted file mode 100644
index f3f59bf3..00000000
--- a/SerpentRace_Backend/src/Application/DTOs/ChatDto.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-export interface CreateChatDto {
- users: string[];
- messages: import('../../Domain/Chat/ChatAggregate').Message[];
- state?: number;
-}
-
-export interface UpdateChatDto {
- id: string;
- users?: string[];
- messages?: import('../../Domain/Chat/ChatAggregate').Message[];
- state?: number;
-}
-
-export interface ShortChatDto {
- id: string;
- userCount: number;
- state: number;
-}
-
-export interface DetailChatDto {
- id: string;
- users: string[];
- messages: import('../../Domain/Chat/ChatAggregate').Message[];
- updateDate: Date;
- state: number;
-}
diff --git a/SerpentRace_Backend/src/Application/DTOs/ContactDto.ts b/SerpentRace_Backend/src/Application/DTOs/ContactDto.ts
deleted file mode 100644
index 44100357..00000000
--- a/SerpentRace_Backend/src/Application/DTOs/ContactDto.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-import { ContactType } from '../../Domain/Contact/ContactAggregate';
-
-export interface CreateContactDto {
- name: string;
- email: string;
- userid?: string;
- type: ContactType;
- txt: string;
-}
-
-export interface UpdateContactDto {
- id: string;
- adminResponse?: string;
- state?: number;
- respondedBy?: string;
-}
-
-export interface ShortContactDto {
- id: string;
- name: string;
- email: string;
- type: ContactType;
- createDate: Date;
- state: number;
-}
-
-export interface DetailContactDto {
- id: string;
- name: string;
- email: string;
- userid: string | null;
- type: ContactType;
- txt: string;
- state: number;
- createDate: Date;
- updateDate: Date;
- adminResponse: string | null;
- responseDate: Date | null;
- respondedBy: string | null;
-}
-
-export interface ContactPageDto {
- contacts: ShortContactDto[];
- totalCount: number;
- from: number;
- to: number;
-}
diff --git a/SerpentRace_Backend/src/Application/DTOs/DeckDto.ts b/SerpentRace_Backend/src/Application/DTOs/DeckDto.ts
deleted file mode 100644
index 68bd74d2..00000000
--- a/SerpentRace_Backend/src/Application/DTOs/DeckDto.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-export interface CreateDeckDto {
- name: string;
- description?: string;
-}
-
-export interface UpdateDeckDto {
- id: string;
- name?: string;
- description?: string;
-}
-
-export interface ShortDeckDto {
- id: string;
- name: string;
- type: number;
- playedNumber: number;
- ctype: number;
- cardCount: number;
- creator: string;
- creationdate: Date;
- editable?: boolean;
-}
-
-export interface DetailDeckDto {
- id: string;
- name: string;
- type: number;
- userid: string;
- creationdate: Date;
- cards: any[];
- playedNumber: number;
- ctype: number;
-}
diff --git a/SerpentRace_Backend/src/Application/DTOs/GameDto.ts b/SerpentRace_Backend/src/Application/DTOs/GameDto.ts
deleted file mode 100644
index 02bc0f61..00000000
--- a/SerpentRace_Backend/src/Application/DTOs/GameDto.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import * as DeckAggregate from "../../Domain/Deck/DeckAggregate";
-
-export interface GameStartDto {
- gameid: string;
- maxplayers: number;
- logintype: number;
- gamecode: string;
- deck: gamedeck[];
-}
-
-enum decktype {
- JOCKER = 0,
- LUCK = 1,
- QUEST = 2
-}
-
-export interface cards {
- cardid: string;
- question?: string;
- answer?: string;
- consequence?: DeckAggregate.Consequence | null;
- played?: boolean;
- playerid?: string;
-}
-
-export interface gamedeck {
- deckid: string;
- decktype: decktype;
- cards: cards[];
-}
-
-export interface GameDataDto {
- id: string;
- gamecode: string;
- maxplayers: number;
- logintype: number;
- gamedecks: gamedeck[];
- players: string[];
- started: boolean;
- finished: boolean;
- winner?: string;
- currentplayer?: string;
- createdate: Date;
- startdate?: Date;
- enddate?: Date;
-}
\ No newline at end of file
diff --git a/SerpentRace_Backend/src/Application/DTOs/Mappers/BaseMapper.ts b/SerpentRace_Backend/src/Application/DTOs/Mappers/BaseMapper.ts
deleted file mode 100644
index d11c5ea4..00000000
--- a/SerpentRace_Backend/src/Application/DTOs/Mappers/BaseMapper.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-export abstract class BaseMapper {
- abstract toShortDto(entity: TEntity): TShortDto;
- abstract toDetailDto(entity: TEntity): TDetailDto;
-
- toShortDtoList(entities: TEntity[]): TShortDto[] {
- return entities.map(entity => this.toShortDto(entity));
- }
-
- toDetailDtoList(entities: TEntity[]): TDetailDto[] {
- return entities.map(entity => this.toDetailDto(entity));
- }
-
- static toShortDtoListStatic(
- entities: T[],
- mapperFn: (entity: T) => TDto
- ): TDto[] {
- return entities.map(mapperFn);
- }
-}
diff --git a/SerpentRace_Backend/src/Application/DTOs/Mappers/ChatMapper.ts b/SerpentRace_Backend/src/Application/DTOs/Mappers/ChatMapper.ts
deleted file mode 100644
index 60507b2f..00000000
--- a/SerpentRace_Backend/src/Application/DTOs/Mappers/ChatMapper.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { ChatAggregate } from '../../../Domain/Chat/ChatAggregate';
-import { ShortChatDto, DetailChatDto } from '../ChatDto';
-
-export class ChatMapper {
- static toShortDto(chat: ChatAggregate): ShortChatDto {
- return {
- id: chat.id,
- userCount: chat.users?.length ?? 0,
- state: chat.state,
- };
- }
-
- static toDetailDto(chat: ChatAggregate): DetailChatDto {
- return {
- id: chat.id,
- users: chat.users ?? [],
- messages: chat.messages,
- updateDate: chat.updateDate,
- state: chat.state,
- };
- }
-
- static toShortDtoList(chats: ChatAggregate[]): ShortChatDto[] {
- return chats.map(this.toShortDto);
- }
-}
diff --git a/SerpentRace_Backend/src/Application/DTOs/Mappers/ContactMapper.ts b/SerpentRace_Backend/src/Application/DTOs/Mappers/ContactMapper.ts
deleted file mode 100644
index b9a23ed1..00000000
--- a/SerpentRace_Backend/src/Application/DTOs/Mappers/ContactMapper.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import { ContactAggregate } from '../../../Domain/Contact/ContactAggregate';
-import { CreateContactDto, UpdateContactDto, ShortContactDto, DetailContactDto } from '../ContactDto';
-
-export class ContactMapper {
- static toShortDto(contact: ContactAggregate): ShortContactDto {
- return {
- id: contact.id,
- name: contact.name,
- email: contact.email,
- type: contact.type,
- createDate: contact.createDate,
- state: contact.state,
- };
- }
-
- static toDetailDto(contact: ContactAggregate): DetailContactDto {
- return {
- id: contact.id,
- name: contact.name,
- email: contact.email,
- userid: contact.userid,
- type: contact.type,
- txt: contact.txt,
- state: contact.state,
- createDate: contact.createDate,
- updateDate: contact.updateDate,
- adminResponse: contact.adminResponse,
- responseDate: contact.responseDate,
- respondedBy: contact.respondedBy,
- };
- }
-
- static toShortDtoList(contacts: ContactAggregate[]): ShortContactDto[] {
- return contacts.map(this.toShortDto);
- }
-}
diff --git a/SerpentRace_Backend/src/Application/DTOs/Mappers/DeckMapper.ts b/SerpentRace_Backend/src/Application/DTOs/Mappers/DeckMapper.ts
deleted file mode 100644
index 87946870..00000000
--- a/SerpentRace_Backend/src/Application/DTOs/Mappers/DeckMapper.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import { DeckAggregate } from '../../../Domain/Deck/DeckAggregate';
-import { UserAggregate } from '../../../Domain/User/UserAggregate';
-import { CreateDeckDto, UpdateDeckDto, ShortDeckDto, DetailDeckDto } from '../DeckDto';
-
-export class DeckMapper {
- static toShortDto(deck: DeckAggregate, userId?: string): ShortDeckDto {
- return {
- id: deck.id,
- name: deck.name,
- type: deck.type,
- playedNumber: deck.playedNumber,
- ctype: deck.ctype,
- cardCount: deck.cards.length,
- creator: deck.user?.username || 'Unknown',
- creationdate: deck.creationdate,
- editable: deck.isEditable(userId!) ? deck.isEditable(userId!) : undefined
- };
- }
-
- static toDetailDto(deck: DeckAggregate): DetailDeckDto {
- return {
- id: deck.id,
- name: deck.name,
- type: deck.type,
- userid: deck.userid,
- creationdate: deck.creationdate,
- cards: deck.cards,
- playedNumber: deck.playedNumber,
- ctype: deck.ctype,
- };
- }
-
- static toShortDtoList(decks: DeckAggregate[], userId?: string): ShortDeckDto[] {
- return decks.map(deck => ({
- id: deck.id,
- name: deck.name,
- type: deck.type,
- playedNumber: deck.playedNumber,
- ctype: deck.ctype,
- cardCount: deck.cards.length,
- creator: deck.user?.username || 'Unknown',
- creationdate: deck.creationdate,
- editable: deck.isEditable(userId!) ? deck.isEditable(userId!) : undefined
- }));
- }
-}
diff --git a/SerpentRace_Backend/src/Application/DTOs/Mappers/OrganizationMapper.ts b/SerpentRace_Backend/src/Application/DTOs/Mappers/OrganizationMapper.ts
deleted file mode 100644
index 70ff5352..00000000
--- a/SerpentRace_Backend/src/Application/DTOs/Mappers/OrganizationMapper.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import { OrganizationAggregate } from '../../../Domain/Organization/OrganizationAggregate';
-import { CreateOrganizationDto, UpdateOrganizationDto, ShortOrganizationDto, DetailOrganizationDto } from '../OrganizationDto';
-
-export class OrganizationMapper {
- static toShortDto(org: OrganizationAggregate): ShortOrganizationDto {
- return {
- id: org.id,
- name: org.name,
- state: org.state,
- userinorg: org.userinorg,
- maxOrganizationalDecks: org.maxOrganizationalDecks,
- };
- }
-
- static toDetailDto(org: OrganizationAggregate): DetailOrganizationDto {
- return {
- id: org.id,
- name: org.name,
- contactfname: org.contactfname,
- contactlname: org.contactlname,
- contactphone: org.contactphone,
- contactemail: org.contactemail,
- state: org.state,
- regdate: org.regdate,
- updateDate: org.updateDate,
- url: org.url,
- userinorg: org.userinorg,
- maxOrganizationalDecks: org.maxOrganizationalDecks,
- users: org.users?.map(u => u.id) ?? [],
- };
- }
-
- static toShortDtoList(orgs: OrganizationAggregate[]): ShortOrganizationDto[] {
- return orgs.map(this.toShortDto);
- }
-}
diff --git a/SerpentRace_Backend/src/Application/DTOs/Mappers/UserMapper.ts b/SerpentRace_Backend/src/Application/DTOs/Mappers/UserMapper.ts
deleted file mode 100644
index 877ccc0f..00000000
--- a/SerpentRace_Backend/src/Application/DTOs/Mappers/UserMapper.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import { UserAggregate, UserState } from '../../../Domain/User/UserAggregate';
-import { CreateUserDto, UpdateUserDto, ShortUserDto, DetailUserDto } from '../UserDto';
-import { BaseMapper } from './BaseMapper';
-
-export class UserMapper {
- static toShortDto(user: UserAggregate): ShortUserDto {
- return {
- username: user.username,
- authLevel: (user.state === UserState.ADMIN ? 1 : 0) as 0 | 1,
- };
- }
-
- static toDetailDto(user: UserAggregate): DetailUserDto {
- return {
- id: user.id,
- orgid: user.orgid,
- username: user.username,
- email: user.email,
- fname: user.fname,
- lname: user.lname,
- code: user.token,
- phone: user.phone,
- state: user.state,
- };
- }
-
- static toShortDtoList(users: UserAggregate[]): ShortUserDto[] {
- return BaseMapper.toShortDtoListStatic(users, UserMapper.toShortDto);
- }
-}
diff --git a/SerpentRace_Backend/src/Application/DTOs/OrganizationDto.ts b/SerpentRace_Backend/src/Application/DTOs/OrganizationDto.ts
deleted file mode 100644
index c1eb4aaf..00000000
--- a/SerpentRace_Backend/src/Application/DTOs/OrganizationDto.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-export interface CreateOrganizationDto {
- name: string;
- description?: string;
- maxOrganizationalDecks?: number | null;
-}
-
-export interface UpdateOrganizationDto {
- id: string;
- name?: string;
- description?: string;
-}
-
-export interface ShortOrganizationDto {
- id: string;
- name: string;
- state: number;
- userinorg: number;
- maxOrganizationalDecks?: number | null;
-}
-
-export interface DetailOrganizationDto {
- id: string;
- name: string;
- contactfname: string;
- contactlname: string;
- contactphone: string;
- contactemail: string;
- state: number;
- regdate: Date;
- updateDate: Date;
- url: string | null;
- userinorg: number;
- maxOrganizationalDecks: number | null;
- users: string[];
-}
-
-export interface OrganizationLoginUrlDto {
- organizationId: string;
- organizationName: string;
- loginUrl: string;
-}
-
-export interface OrganizationAuthCallbackDto {
- organizationId: string;
- userId: string;
- status: 'ok' | 'not_ok';
- authToken?: string;
-}
diff --git a/SerpentRace_Backend/src/Application/DTOs/SearchDto.ts b/SerpentRace_Backend/src/Application/DTOs/SearchDto.ts
deleted file mode 100644
index acb616d8..00000000
--- a/SerpentRace_Backend/src/Application/DTOs/SearchDto.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-export interface SearchQuery {
- query: string;
- limit?: number;
- offset?: number;
-}
-
-export interface SearchResult {
- results: T[];
- totalCount: number;
- hasMore: boolean;
- searchQuery: string;
- searchType: 'users' | 'organizations' | 'decks';
-}
diff --git a/SerpentRace_Backend/src/Application/DTOs/UserDto.ts b/SerpentRace_Backend/src/Application/DTOs/UserDto.ts
deleted file mode 100644
index d3a68ab7..00000000
--- a/SerpentRace_Backend/src/Application/DTOs/UserDto.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-export interface CreateUserDto {
- username: string;
- email: string;
-}
-
-export interface UpdateUserDto {
- id: string;
- username?: string;
- email?: string;
-}
-
-export interface ShortUserDto {
- username: string;
- authLevel: 0 | 1;
-}
-
-export interface DetailUserDto {
- id: string;
- orgid: string | null;
- username: string;
- email: string;
- fname: string;
- lname: string;
- code: string | null;
- phone: string | null;
- state: number;
-}
diff --git a/SerpentRace_Backend/src/Application/Deck/commands/CreateDeckCommand.ts b/SerpentRace_Backend/src/Application/Deck/commands/CreateDeckCommand.ts
deleted file mode 100644
index 9e4ec5ad..00000000
--- a/SerpentRace_Backend/src/Application/Deck/commands/CreateDeckCommand.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-export interface CreateDeckCommand {
- name: string;
- type: number;
- userid: string;
- cards: any[];
- ctype?: number;
-}
diff --git a/SerpentRace_Backend/src/Application/Deck/commands/CreateDeckCommandHandler.ts b/SerpentRace_Backend/src/Application/Deck/commands/CreateDeckCommandHandler.ts
deleted file mode 100644
index c6c75d2f..00000000
--- a/SerpentRace_Backend/src/Application/Deck/commands/CreateDeckCommandHandler.ts
+++ /dev/null
@@ -1,125 +0,0 @@
-import { IDeckRepository } from '../../../Domain/IRepository/IDeckRepository';
-import { IUserRepository } from '../../../Domain/IRepository/IUserRepository';
-import { IOrganizationRepository } from '../../../Domain/IRepository/IOrganizationRepository';
-import { CreateDeckCommand } from './CreateDeckCommand';
-import { ShortDeckDto } from '../../DTOs/DeckDto';
-import { DeckAggregate, State, CType } from '../../../Domain/Deck/DeckAggregate';
-import { UserState } from '../../../Domain/User/UserAggregate';
-import { DeckMapper } from '../../DTOs/Mappers/DeckMapper';
-import { AdminBypassService } from '../../Services/AdminBypassService';
-import { logRequest } from '../../Services/Logger';
-
-export class CreateDeckCommandHandler {
- constructor(
- private readonly deckRepo: IDeckRepository,
- private readonly userRepo: IUserRepository,
- private readonly orgRepo: IOrganizationRepository
- ) {}
-
- async execute(cmd: CreateDeckCommand): Promise {
- try {
- // 1. Get user details
- const user = await this.userRepo.findById(cmd.userid);
- if (!user) {
- throw new Error('User not found');
- }
-
- // 2. ADMIN BYPASS - Skip all restrictions
- if (AdminBypassService.shouldBypassRestrictions(user.state)) {
- AdminBypassService.logAdminBypass(
- 'CREATE_DECK_BYPASS',
- user.id,
- 'new-deck',
- {
- deckName: cmd.name,
- deckType: cmd.type,
- cardCount: cmd.cards.length,
- ctype: cmd.ctype
- }
- );
- return this.createDeck(cmd);
- }
-
- // 3. Check deck count limits for regular users
- const userDeckCount = await this.deckRepo.countActiveByUserId(cmd.userid);
- const maxDecks = user.state === UserState.VERIFIED_PREMIUM ? 12 : 8;
-
- if (userDeckCount >= maxDecks) {
- throw new Error(`Deck limit exceeded. Maximum ${maxDecks} decks allowed for your account type.`);
- }
-
- // 4. Organizational deck restrictions
- if (cmd.ctype === CType.ORGANIZATION) {
- // Only premium users can create organizational decks
- if (user.state !== UserState.VERIFIED_PREMIUM) {
- throw new Error('Only premium users can create organizational decks.');
- }
-
- // User must belong to an organization
- if (!user.orgid) {
- throw new Error('You must be a member of an organization to create organizational decks.');
- }
-
- // Check organization limits
- const org = await this.orgRepo.findById(user.orgid);
- if (!org) {
- throw new Error('Organization not found.');
- }
-
- if (org.maxOrganizationalDecks === null) {
- throw new Error('Organization deck limit not configured. Contact administrator.');
- }
-
- const userOrgDeckCount = await this.deckRepo.countOrganizationalByUserId(cmd.userid);
- if (userOrgDeckCount >= org.maxOrganizationalDecks) {
- throw new Error(`Organization deck limit exceeded. Maximum ${org.maxOrganizationalDecks} organizational decks allowed.`);
- }
- }
-
- // 5. Create deck with restrictions passed
- return this.createDeck(cmd);
- } catch (error) {
- if (error instanceof Error) {
- throw error; // Re-throw known errors with original message
- }
- throw new Error('Failed to create deck');
- }
- }
-
- /**
- * Private method to create deck after all validations
- */
- private async createDeck(cmd: CreateDeckCommand): Promise {
- const deck = new DeckAggregate();
- deck.name = cmd.name;
- deck.type = cmd.type;
- deck.userid = cmd.userid;
- deck.cards = cmd.cards;
- deck.ctype = cmd.ctype ?? CType.PUBLIC;
- deck.state = State.ACTIVE;
-
- // Set organization reference for organizational decks
- if (cmd.ctype === CType.ORGANIZATION) {
- const user = await this.userRepo.findById(cmd.userid);
- if (user?.orgid) {
- const org = await this.orgRepo.findById(user.orgid);
- if (org) {
- deck.organization = org;
- }
- }
- }
-
- const created = await this.deckRepo.create(deck);
-
- logRequest('Deck created successfully', undefined, undefined, {
- deckId: created.id,
- userId: cmd.userid,
- deckName: cmd.name,
- deckType: cmd.type,
- ctype: cmd.ctype,
- cardCount: cmd.cards.length
- });
-
- return DeckMapper.toShortDto(created);
- }
-}
diff --git a/SerpentRace_Backend/src/Application/Deck/commands/DeleteDeckCommand.ts b/SerpentRace_Backend/src/Application/Deck/commands/DeleteDeckCommand.ts
deleted file mode 100644
index d41de235..00000000
--- a/SerpentRace_Backend/src/Application/Deck/commands/DeleteDeckCommand.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export interface DeleteDeckCommand {
- userid: string;
- authLevel: number;
- id: string;
- soft?: boolean;
-}
diff --git a/SerpentRace_Backend/src/Application/Deck/commands/DeleteDeckCommandHandler.ts b/SerpentRace_Backend/src/Application/Deck/commands/DeleteDeckCommandHandler.ts
deleted file mode 100644
index 07309b19..00000000
--- a/SerpentRace_Backend/src/Application/Deck/commands/DeleteDeckCommandHandler.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import { IDeckRepository } from '../../../Domain/IRepository/IDeckRepository';
-import { logAuth, logError } from '../../Services/Logger';
-import { DeleteDeckCommand } from './DeleteDeckCommand';
-
-export class DeleteDeckCommandHandler {
- constructor(private readonly deckRepo: IDeckRepository) {}
-
- async execute(cmd: DeleteDeckCommand): Promise {
-
- //get decks userid
- const deck = await this.deckRepo.findById(cmd.id);
- if (!deck) {
- logError(`Deck not found with ID: ${cmd.id}`);
- throw new Error('Deck not found');
- }
-
- if(cmd.authLevel !==1 && deck.userid !== cmd.userid) {
- logAuth(`Unauthorized access attempt to deck with ID: ${cmd.id}, UserID: ${cmd.userid}`);
- throw new Error('Unauthorized');
- }
-
- if (cmd.soft) {
- await this.deckRepo.softDelete(cmd.id);
- } else {
- await this.deckRepo.delete(cmd.id);
- }
- return true;
- }
-}
diff --git a/SerpentRace_Backend/src/Application/Deck/commands/UpdateDeckCommand.ts b/SerpentRace_Backend/src/Application/Deck/commands/UpdateDeckCommand.ts
deleted file mode 100644
index 9fbbb3a9..00000000
--- a/SerpentRace_Backend/src/Application/Deck/commands/UpdateDeckCommand.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-export interface UpdateDeckCommand {
- userid: string;
- authLevel: number;
- id: string;
- userstate?: number;
- name?: string;
- type?: number;
- cards?: any[];
- ctype?: number;
- state?: number;
-}
diff --git a/SerpentRace_Backend/src/Application/Deck/commands/UpdateDeckCommandHandler.ts b/SerpentRace_Backend/src/Application/Deck/commands/UpdateDeckCommandHandler.ts
deleted file mode 100644
index 85cc4202..00000000
--- a/SerpentRace_Backend/src/Application/Deck/commands/UpdateDeckCommandHandler.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-import { IDeckRepository } from '../../../Domain/IRepository/IDeckRepository';
-import { UpdateDeckCommand } from './UpdateDeckCommand';
-import { ShortDeckDto } from '../../DTOs/DeckDto';
-import { DeckMapper } from '../../DTOs/Mappers/DeckMapper';
-import { DeckAggregate } from '../../../Domain/Deck/DeckAggregate';
-import { logAuth, logError } from '../../Services/Logger';
-
-export class UpdateDeckCommandHandler {
- constructor(private readonly deckRepo: IDeckRepository) {}
-
- async execute(cmd: UpdateDeckCommand): Promise {
- if(cmd.state !== undefined && cmd.authLevel !== 1) {
- throw new Error('Only admin users can change deck state');
- }
- try {
- let existingDeck: DeckAggregate | null = null;
- if (cmd.authLevel === 1) {
- existingDeck = await this.deckRepo.findByIdIncludingDeleted(cmd.id);
- } else {
- existingDeck = await this.deckRepo.findById(cmd.id);
- }
- if (!existingDeck) {
- logError(`Deck not found with ID: ${cmd.id}`);
- throw new Error('Deck not found');
- }
-
- if(cmd.authLevel !== 1 && existingDeck.userid !== cmd.userid) {
- logAuth(`Unauthorized access attempt to deck with ID: ${cmd.id}, UserID: ${cmd.userid}`);
- throw new Error('Unauthorized');
- }
-
- const for_update: Partial = {};
- if(cmd.name !== undefined) for_update.name = cmd.name;
- if(cmd.type !== undefined) for_update.type = cmd.type;
- if(cmd.cards !== undefined) for_update.cards = cmd.cards;
- if(cmd.ctype !== undefined) for_update.ctype = cmd.ctype;
- if(cmd.state !== undefined) for_update.state = cmd.state;
-
- // Ensure we have something to update
- if (Object.keys(for_update).length === 0) {
- throw new Error('No fields provided for update');
- }
-
- const deck = await this.deckRepo.update(cmd.id, { ...for_update });
- if(!deck) {
- logError(`Deck update failed for ID: ${cmd.id}. Update returned null.`);
- throw new Error('Failed to update deck');
- }
- return DeckMapper.toShortDto(deck);
- } catch (error: any) {
- logError(`Error updating deck: ${cmd.id}`, error);
- throw error;
- }
- }
-}
diff --git a/SerpentRace_Backend/src/Application/Deck/queries/GetDeckByIdQuery.ts b/SerpentRace_Backend/src/Application/Deck/queries/GetDeckByIdQuery.ts
deleted file mode 100644
index 49c192e0..00000000
--- a/SerpentRace_Backend/src/Application/Deck/queries/GetDeckByIdQuery.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export interface GetDeckByIdQuery {
- id: string;
-}
diff --git a/SerpentRace_Backend/src/Application/Deck/queries/GetDeckByIdQueryHandler.ts b/SerpentRace_Backend/src/Application/Deck/queries/GetDeckByIdQueryHandler.ts
deleted file mode 100644
index 9ea429b4..00000000
--- a/SerpentRace_Backend/src/Application/Deck/queries/GetDeckByIdQueryHandler.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { IDeckRepository } from '../../../Domain/IRepository/IDeckRepository';
-import { GetDeckByIdQuery } from './GetDeckByIdQuery';
-import { DetailDeckDto } from '../../DTOs/DeckDto';
-import { DeckMapper } from '../../DTOs/Mappers/DeckMapper';
-
-export class GetDeckByIdQueryHandler {
- constructor(private readonly deckRepo: IDeckRepository) {}
-
- async execute(query: GetDeckByIdQuery): Promise {
- const deck = await this.deckRepo.findById(query.id);
- if (!deck) return null;
- return DeckMapper.toDetailDto(deck);
- }
-}
diff --git a/SerpentRace_Backend/src/Application/Deck/queries/GetDecksByPageQuery.ts b/SerpentRace_Backend/src/Application/Deck/queries/GetDecksByPageQuery.ts
deleted file mode 100644
index 370fe350..00000000
--- a/SerpentRace_Backend/src/Application/Deck/queries/GetDecksByPageQuery.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export interface GetDecksByPageQuery {
- from: number;
- to: number;
- userId: string;
- userOrgId?: string;
- isAdmin: boolean;
- includeDeleted?: boolean;
-}
diff --git a/SerpentRace_Backend/src/Application/Deck/queries/GetDecksByPageQueryHandler.ts b/SerpentRace_Backend/src/Application/Deck/queries/GetDecksByPageQueryHandler.ts
deleted file mode 100644
index a4e6086a..00000000
--- a/SerpentRace_Backend/src/Application/Deck/queries/GetDecksByPageQueryHandler.ts
+++ /dev/null
@@ -1,82 +0,0 @@
-import { IDeckRepository } from '../../../Domain/IRepository/IDeckRepository';
-import { GetDecksByPageQuery } from './GetDecksByPageQuery';
-import { ShortDeckDto } from '../../DTOs/DeckDto';
-import { DeckMapper } from '../../DTOs/Mappers/DeckMapper';
-import { AdminBypassService } from '../../Services/AdminBypassService';
-import { logRequest, logError } from '../../Services/Logger';
-
-export class GetDecksByPageQueryHandler {
- constructor(private readonly deckRepo: IDeckRepository) {}
-
- async execute(query: GetDecksByPageQuery): Promise<{ decks: ShortDeckDto[], totalCount: number }> {
- try {
- // Validate pagination parameters
- if (query.from < 0 || query.to < query.from) {
- throw new Error('Invalid pagination parameters');
- }
-
- const limit = query.to - query.from + 1;
- if (limit > 100) {
- throw new Error('Page size too large. Maximum 100 records per request');
- }
-
- // Log admin bypass if applicable
- if (query.isAdmin) {
- AdminBypassService.logAdminBypass(
- 'GET_DECKS_PAGE_BYPASS',
- query.userId,
- 'paginated-decks',
- {
- from: query.from,
- to: query.to,
- includesDeleted: query.includeDeleted || false,
- operation: 'read'
- }
- );
- }
-
- logRequest('Get decks by page query started', undefined, undefined, {
- userId: query.userId,
- userOrgId: query.userOrgId,
- isAdmin: query.isAdmin,
- from: query.from,
- to: query.to,
- includeDeleted: query.includeDeleted || false
- });
-
- // Use paginated filtered deck finding method
- const result = await this.deckRepo.findFilteredDecks(
- query.userId,
- query.userOrgId,
- query.isAdmin,
- query.from,
- query.to
- );
-
- logRequest('Get decks by page query completed', undefined, undefined, {
- userId: query.userId,
- userOrgId: query.userOrgId,
- isAdmin: query.isAdmin,
- from: query.from,
- to: query.to,
- returned: result.decks.length,
- totalCount: result.totalCount,
- includeDeleted: query.includeDeleted || false
- });
-
- return {
- decks: DeckMapper.toShortDtoList(result.decks, query.userId),
- totalCount: result.totalCount
- };
- } catch (error) {
- logError('GetDecksByPageQueryHandler error', error instanceof Error ? error : new Error(String(error)));
-
- // Re-throw validation errors as-is
- if (error instanceof Error && (error.message.includes('Invalid pagination') || error.message.includes('Page size'))) {
- throw error;
- }
-
- throw new Error('Failed to retrieve decks page');
- }
- }
-}
diff --git a/SerpentRace_Backend/src/Application/Game/BoardGenerationService.ts b/SerpentRace_Backend/src/Application/Game/BoardGenerationService.ts
deleted file mode 100644
index e952bfe7..00000000
--- a/SerpentRace_Backend/src/Application/Game/BoardGenerationService.ts
+++ /dev/null
@@ -1,209 +0,0 @@
-import { GameField, BoardData } from '../../Domain/Game/GameAggregate';
-import { logOther, logError } from '../Services/Logger';
-
-interface SpecialFieldInfo {
- position: number;
- type: 'positive' | 'negative' | 'luck';
-}
-
-export class BoardGenerationService {
- async generateBoard(
- positiveFieldCount: number,
- negativeFieldCount: number,
- luckFieldCount: number
- ): Promise {
- // Pattern-based approach has 100% success rate, no retry needed
- const result = this.generateSingleAttempt(positiveFieldCount, negativeFieldCount, luckFieldCount);
-
- logOther('Pattern-based board generation completed', {
- totalFields: result.fields.length,
- specialFields: result.fields.filter((f: GameField) => f.type !== 'regular').length,
- positiveFields: result.fields.filter((f: GameField) => f.type === 'positive').length,
- negativeFields: result.fields.filter((f: GameField) => f.type === 'negative').length,
- luckFields: result.fields.filter((f: GameField) => f.type === 'luck').length
- });
-
- return result;
- }
-
- private generateSingleAttempt(
- positiveFieldCount: number,
- negativeFieldCount: number,
- luckFieldCount: number
- ): BoardData {
- // Step 1: Choose special field positions
- const specialFieldPositions = this.chooseSpecialFieldPositions(
- positiveFieldCount,
- negativeFieldCount,
- luckFieldCount
- );
-
- // Step 2: Calculate step values using pattern-based approach
- const fields = this.calculatePatternBasedStepValues(specialFieldPositions);
-
- return {
- fields
- };
- }
-
- private chooseSpecialFieldPositions(
- positiveFieldCount: number,
- negativeFieldCount: number,
- luckFieldCount: number
- ): SpecialFieldInfo[] {
- const totalSpecial = positiveFieldCount + negativeFieldCount + luckFieldCount;
- const specialFields: SpecialFieldInfo[] = [];
-
- // Generate unique random positions
- const positions = new Set();
- while (positions.size < totalSpecial) {
- const position = Math.floor(Math.random() * 100) + 1; // 1-100
- positions.add(position);
- }
-
- // Convert to sorted array
- const sortedPositions = Array.from(positions).sort((a, b) => a - b);
-
- // Distribute types randomly
- const types: ('positive' | 'negative' | 'luck')[] = [
- ...Array(positiveFieldCount).fill('positive'),
- ...Array(negativeFieldCount).fill('negative'),
- ...Array(luckFieldCount).fill('luck')
- ];
-
- // Shuffle types
- for (let i = types.length - 1; i > 0; i--) {
- const j = Math.floor(Math.random() * (i + 1));
- [types[i], types[j]] = [types[j], types[i]];
- }
-
- sortedPositions.forEach((position, index) => {
- specialFields.push({
- position,
- type: types[index] || 'positive'
- });
- });
-
- return specialFields;
- }
-
- private calculatePatternBasedStepValues(specialFields: SpecialFieldInfo[]): GameField[] {
- // Initialize all fields as regular
- const fields: GameField[] = Array.from({ length: 100 }, (_, i) => ({
- position: i + 1,
- type: 'regular' as const
- }));
-
- // Update special fields with pattern-based step values
- specialFields.forEach(specialField => {
- const fieldIndex = specialField.position - 1; // Convert to 0-based index
- fields[fieldIndex].type = specialField.type;
-
- if (specialField.type === 'luck') {
- // Luck fields don't need step values
- return;
- }
-
- // Calculate step values based on position rules
- let maxStepValue: number;
- let minStepValue: number;
-
- if (specialField.position <= 80) {
- // Positions 1-80: step values can be ±20
- maxStepValue = 20;
- minStepValue = -20;
- } else {
- // Positions 81-100: step values can be -30 to +10
- maxStepValue = 10;
- minStepValue = -30;
- }
-
- // Generate appropriate step value for field type
- if (specialField.type === 'positive') {
- // Positive fields: use positive step values (1-3 range for balanced gameplay)
- // Max movement: 3 Ă 6 (dice) = 18 steps
- const stepValue = Math.floor(Math.random() * 3) + 1; // 1-3
- fields[fieldIndex].stepValue = Math.min(stepValue, maxStepValue);
- } else {
- // Negative fields: use negative step values (-1 to -3 range)
- // Max backward: -3 Ă 6 (dice) = -18 steps
- const stepValue = -(Math.floor(Math.random() * 3) + 1); // -1 to -3
- fields[fieldIndex].stepValue = Math.max(stepValue, minStepValue);
- }
- });
-
- return fields;
- }
-
- // This method can be used by FieldEffectService for movement calculations
- public calculatePatternBasedMovement(
- currentPosition: number,
- stepValue: number,
- diceValue: number
- ): number {
- // Calculate pattern modifier based on current position
- const patternModifier = this.getPatternModifier(currentPosition, stepValue > 0);
-
- // Calculate final position: currentPosition + (stepValue Ă dice) + patternModifier
- const movement = stepValue * diceValue;
- let finalPosition = currentPosition + movement + patternModifier;
-
- // Ensure position stays within board bounds (1-100)
- if (finalPosition < 1) {
- finalPosition = 1;
- } else if (finalPosition > 100) {
- finalPosition = 100;
- }
-
- return finalPosition;
- }
-
- public getPatternModifier(position: number, positiveField: boolean): number {
- // Pattern modifiers STACK for strategic complexity:
- // - Positions ending in 0 (10, 20, 30...): No modifier
- // - Positions ending in 5 (15, 25, 35...): ±3 modifier
- // - Positions divisible by 3 (9, 12, 21...): ±2 modifier
- // - Odd positions (1, 7, 11...): ±1 modifier
- // Multiple conditions can apply and stack
-
- if (position % 10 === 0) {
- return 0; // Positions ending in 0 - no modifier
- }
-
- let modifier = 0;
- const direction = positiveField ? 1 : -1;
-
- // Check each condition and stack modifiers
- if (position % 10 === 5) {
- modifier += 3 * direction; // Positions ending in 5
- }
- if (position % 3 === 0) {
- modifier += 2 * direction; // Divisible by 3
- }
- if (position % 2 === 1) {
- modifier += 1 * direction; // Odd positions
- }
-
- return modifier;
- }
-
- private validate20_30Rule(currentPosition: number, targetPosition: number, distance: number): boolean {
- // Fields 1-85: max 20 fields in any direction
- if (currentPosition <= 85) {
- return distance <= 20;
- }
-
- // Fields 86-100: max 30 fields backward, max 20 fields forward
- if (currentPosition > 85) {
- if (targetPosition > currentPosition) {
- // Moving forward: max 20 fields
- return distance <= 20;
- } else {
- // Moving backward: max 30 fields
- return distance <= 30;
- }
- }
-
- return false;
- }
-}
\ No newline at end of file
diff --git a/SerpentRace_Backend/src/Application/Game/GameService.ts b/SerpentRace_Backend/src/Application/Game/GameService.ts
deleted file mode 100644
index dd941e6a..00000000
--- a/SerpentRace_Backend/src/Application/Game/GameService.ts
+++ /dev/null
@@ -1,303 +0,0 @@
-import { StartGameCommand } from './commands/StartGameCommand';
-import { StartGameCommandHandler } from './commands/StartGameCommandHandler';
-import { JoinGameCommand } from './commands/JoinGameCommand';
-import { JoinGameCommandHandler } from './commands/JoinGameCommandHandler';
-import { StartGamePlayCommand } from './commands/StartGamePlayCommand';
-import { StartGamePlayCommandHandler, GameStartResult } from './commands/StartGamePlayCommandHandler';
-import { GameAggregate, LoginType } from '../../Domain/Game/GameAggregate';
-import { logOther, logError } from '../Services/Logger';
-
-export class GameService {
- private startGameHandler: StartGameCommandHandler;
- private joinGameHandler: JoinGameCommandHandler;
- private startGamePlayHandler: StartGamePlayCommandHandler;
-
- constructor() {
- this.startGameHandler = new StartGameCommandHandler();
- this.joinGameHandler = new JoinGameCommandHandler();
- this.startGamePlayHandler = new StartGamePlayCommandHandler();
- }
-
- /**
- * Starts a new game with the provided deck IDs
- * @param deckids Array of deck IDs (should contain 3 types: LUCK, JOKER, QUESTION)
- * @param maxplayers Maximum number of players allowed in the game
- * @param logintype How players can join the game (PUBLIC, PRIVATE, ORGANIZATION)
- * @param userid Optional ID of the user creating the game
- * @returns Promise The created game
- */
- async startGame(
- deckids: string[],
- maxplayers: number,
- logintype: LoginType,
- userid?: string,
- orgid?: string | null
- ): Promise {
- const startTime = performance.now();
-
- try {
- logOther('GameService.startGame called', {
- deckCount: deckids.length,
- maxplayers,
- logintype,
- userid,
- orgid
- });
-
- // Validate input parameters
- this.validateStartGameInput(deckids, maxplayers, logintype);
-
- // Create and execute the command
- const command: StartGameCommand = {
- deckids,
- maxplayers,
- logintype,
- userid,
- orgid
- };
-
- const game = await this.startGameHandler.handle(command);
-
- const endTime = performance.now();
- logOther('Game started successfully', {
- gameId: game.id,
- gameCode: game.gamecode,
- deckCount: game.gamedecks.length,
- totalCards: game.gamedecks.reduce((sum, deck) => sum + deck.cards.length, 0),
- executionTime: Math.round(endTime - startTime)
- });
-
- return game;
-
- } catch (error) {
- const endTime = performance.now();
- logError('GameService.startGame failed', error instanceof Error ? error : new Error(String(error)));
- logOther('Game start failed', {
- executionTime: Math.round(endTime - startTime),
- error: error instanceof Error ? error.message : String(error)
- });
- throw error;
- }
- }
-
- /**
- * Join an existing game using game code
- * @param gameCode 6-character game code
- * @param playerId ID of the player joining (optional for public games)
- * @param playerName Display name for the player
- * @param orgId Organization ID (for organization games)
- * @param loginType Type of join being attempted
- * @returns Promise The updated game with new player
- */
- async joinGame(
- gameCode: string,
- playerId?: string,
- playerName?: string,
- orgId?: string | null,
- loginType?: LoginType
- ): Promise {
- const startTime = performance.now();
-
- try {
- logOther('GameService.joinGame called', {
- gameCode,
- playerId: playerId || 'anonymous',
- playerName,
- orgId,
- loginType
- });
-
- // Validate input parameters
- this.validateJoinGameInput(gameCode, playerId, loginType);
-
- // Create and execute the command
- const command: JoinGameCommand = {
- gameCode,
- playerId,
- playerName,
- orgId,
- loginType: loginType || LoginType.PUBLIC
- };
-
- const game = await this.joinGameHandler.handle(command);
-
- const endTime = performance.now();
- logOther('Player joined game successfully', {
- gameId: game.id,
- gameCode: game.gamecode,
- playerId,
- playerCount: game.players.length,
- maxPlayers: game.maxplayers,
- executionTime: Math.round(endTime - startTime)
- });
-
- return game;
-
- } catch (error) {
- const endTime = performance.now();
- logError('GameService.joinGame failed', error instanceof Error ? error : new Error(String(error)));
- logOther('Game join failed', {
- gameCode,
- playerId,
- executionTime: Math.round(endTime - startTime),
- error: error instanceof Error ? error.message : String(error)
- });
- throw error;
- }
- }
-
- /**
- * Start an existing game (move from WAITING to ACTIVE)
- * Initializes all player positions to 0 and assigns random turn order
- * @param gameId Game ID to start
- * @param userId User ID of the game master (optional for public games)
- * @returns Promise The updated game
- */
- async startGamePlay(
- gameId: string,
- userId?: string
- ): Promise {
- const startTime = performance.now();
-
- try {
- logOther('GameService.startGamePlay called', {
- gameId,
- userId: userId || 'system'
- });
-
- // Validate input parameters
- this.validateStartGamePlayInput(gameId);
-
- // Create and execute the command
- const command: StartGamePlayCommand = {
- gameId,
- userId
- };
-
- const result = await this.startGamePlayHandler.handle(command);
-
- const endTime = performance.now();
- logOther('Game play started successfully', {
- gameId: result.game.id,
- gameCode: result.game.gamecode,
- playerCount: result.game.players.length,
- gameState: result.game.state,
- executionTime: Math.round(endTime - startTime)
- });
-
- return result;
-
- } catch (error) {
- const endTime = performance.now();
- logError('GameService.startGamePlay failed', error instanceof Error ? error : new Error(String(error)));
- logOther('Game play start failed', {
- gameId,
- userId,
- executionTime: Math.round(endTime - startTime),
- error: error instanceof Error ? error.message : String(error)
- });
- throw error;
- }
- }
-
- private validateStartGamePlayInput(gameId: string): void {
- // Validate game ID
- if (!gameId || typeof gameId !== 'string') {
- throw new Error('Game ID is required and must be a string');
- }
-
- logOther('Start game play input validation passed', {
- gameId
- });
- }
-
- private validateJoinGameInput(gameCode: string, playerId?: string, loginType?: LoginType): void {
- // Validate game code
- if (!gameCode || typeof gameCode !== 'string') {
- throw new Error('Game code is required and must be a string');
- }
-
- if (gameCode.length !== 6) {
- throw new Error('Game code must be exactly 6 characters long');
- }
-
- // Validate login type specific requirements
- if (loginType === LoginType.PRIVATE || loginType === LoginType.ORGANIZATION) {
- if (!playerId || typeof playerId !== 'string') {
- throw new Error(`Player ID is required for ${LoginType[loginType]} games`);
- }
- }
-
- logOther('Join game input validation passed', {
- gameCode,
- playerId: playerId || 'anonymous',
- loginType
- });
- }
-
- private validateStartGameInput(deckids: string[], maxplayers: number, logintype: LoginType): void {
- // Validate deck IDs
- if (!deckids || deckids.length === 0) {
- throw new Error('At least one deck ID must be provided');
- }
-
- if (deckids.length < 3) {
- throw new Error('At least 3 decks are required to start a game (one for each type: LUCK, JOKER, QUESTION)');
- }
-
- // Validate max players
- if (!maxplayers || maxplayers < 2) {
- throw new Error('Maximum players must be at least 2');
- }
-
- if (maxplayers > 8) {
- throw new Error('Maximum players cannot exceed 8');
- }
-
- // Validate login type
- if (logintype < 0 || logintype > 2) {
- throw new Error('Invalid login type. Must be PUBLIC (0), PRIVATE (1), or ORGANIZATION (2)');
- }
-
- // Check for duplicate deck IDs
- const uniqueIds = new Set(deckids);
- if (uniqueIds.size !== deckids.length) {
- throw new Error('Duplicate deck IDs are not allowed');
- }
-
- logOther('Start game input validation passed', {
- deckCount: deckids.length,
- maxplayers,
- logintype
- });
- }
-
- /**
- * Game flow explanation (to be implemented later):
- *
- * 1. START GAME (implemented above):
- * - Input: deckids, maxplayers, logintype, gamecode
- * - Process: Fetch decks, validate types, shuffle cards, create game
- * - Output: Game with shuffled deck objects
- *
- * 2. JOIN GAME (to be implemented):
- * - Input: gamecode, playerid
- * - Process: Find game, validate capacity, add player
- * - Output: Updated game with new player
- *
- * 3. GAME ROUNDS (to be implemented):
- * - Input: gameid, current player
- * - Process: Manage turn order, track game state
- * - Output: Current player information
- *
- * 4. PICK CARD (to be implemented):
- * - Input: gameid, playerid, deck type
- * - Process: Draw card from specific deck, apply consequence
- * - Output: Card details and consequence effects
- *
- * 5. END GAME (to be implemented):
- * - Input: gameid, winner
- * - Process: Set game as finished, record winner
- * - Output: Final game state
- */
-}
\ No newline at end of file
diff --git a/SerpentRace_Backend/src/Application/Game/commands/GenerateBoardCommand.ts b/SerpentRace_Backend/src/Application/Game/commands/GenerateBoardCommand.ts
deleted file mode 100644
index b3c909b4..00000000
--- a/SerpentRace_Backend/src/Application/Game/commands/GenerateBoardCommand.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export interface GenerateBoardCommand {
- gameId: string;
- positiveFieldCount: number;
- negativeFieldCount: number;
- luckFieldCount: number;
-}
\ No newline at end of file
diff --git a/SerpentRace_Backend/src/Application/Game/commands/GenerateBoardCommandHandler.ts b/SerpentRace_Backend/src/Application/Game/commands/GenerateBoardCommandHandler.ts
deleted file mode 100644
index f5e454a9..00000000
--- a/SerpentRace_Backend/src/Application/Game/commands/GenerateBoardCommandHandler.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-import { GenerateBoardCommand } from './GenerateBoardCommand';
-import { BoardGenerationService } from '../BoardGenerationService';
-import { RedisService } from '../../Services/RedisService';
-import { logOther, logError } from '../../Services/Logger';
-import { BoardData } from '../../../Domain/Game/GameAggregate';
-
-export class GenerateBoardCommandHandler {
- constructor(
- private readonly boardGenerationService: BoardGenerationService,
- private readonly redisService: RedisService
- ) {}
-
- async execute(cmd: GenerateBoardCommand): Promise {
- try {
- logOther(`Starting board generation for game ${cmd.gameId}`);
- const startTime = Date.now();
-
- // Generate board with 20-30 rule validation
- const boardData = await this.boardGenerationService.generateBoard(
- cmd.positiveFieldCount,
- cmd.negativeFieldCount,
- cmd.luckFieldCount
- );
-
- // Store in Redis
- const boardDataWithMetadata: BoardData = {
- ...boardData,
- gameId: cmd.gameId,
- generatedAt: new Date(),
- generationComplete: true
- };
-
- await this.redisService.setWithExpiry(
- `game_board_${cmd.gameId}`,
- JSON.stringify(boardDataWithMetadata),
- 24 * 60 * 60 // 24 hours
- );
-
- const executionTime = Date.now() - startTime;
- logOther(`Board generation completed for game ${cmd.gameId} in ${executionTime}ms using pattern-based approach`);
-
- } catch (error) {
- logError(`Board generation failed for game ${cmd.gameId}:`, error as Error);
-
- // Store error state in Redis
- const errorData: BoardData = {
- gameId: cmd.gameId,
- fields: [],
- generationComplete: false,
- error: error instanceof Error ? error.message : 'Unknown error',
- generatedAt: new Date()
- };
-
- await this.redisService.setWithExpiry(
- `game_board_${cmd.gameId}`,
- JSON.stringify(errorData),
- 24 * 60 * 60
- );
-
- throw error;
- }
- }
-}
\ No newline at end of file
diff --git a/SerpentRace_Backend/src/Application/Game/commands/JoinGameCommand.ts b/SerpentRace_Backend/src/Application/Game/commands/JoinGameCommand.ts
deleted file mode 100644
index b59e633c..00000000
--- a/SerpentRace_Backend/src/Application/Game/commands/JoinGameCommand.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import { LoginType } from '../../../Domain/Game/GameAggregate';
-
-export interface JoinGameCommand {
- gameCode: string; // 6-character game code
- playerId?: string; // User ID of the player joining (optional for public games)
- playerName?: string; // Display name for the player (required for public games)
- orgId?: string | null; // Organization ID (for organization games)
- loginType: LoginType; // Type of join being attempted
-}
\ No newline at end of file
diff --git a/SerpentRace_Backend/src/Application/Game/commands/JoinGameCommandHandler.ts b/SerpentRace_Backend/src/Application/Game/commands/JoinGameCommandHandler.ts
deleted file mode 100644
index 2fa4dc6a..00000000
--- a/SerpentRace_Backend/src/Application/Game/commands/JoinGameCommandHandler.ts
+++ /dev/null
@@ -1,219 +0,0 @@
-import { JoinGameCommand } from './JoinGameCommand';
-import { GameAggregate, GameState, LoginType } from '../../../Domain/Game/GameAggregate';
-import { IGameRepository } from '../../../Domain/IRepository/IGameRepository';
-import { DIContainer } from '../../Services/DIContainer';
-import { RedisService } from '../../Services/RedisService';
-import { logOther, logError } from '../../Services/Logger';
-import { v4 as uuidv4 } from 'uuid';
-
-export interface GamePlayerData {
- playerId: string;
- playerName?: string;
- joinedAt: Date;
- isOnline: boolean;
- position?: number; // For game board position (to be used later)
-}
-
-export interface ActiveGameData {
- gameId: string;
- gameCode: string;
- hostId?: string;
- maxPlayers: number;
- currentPlayers: GamePlayerData[];
- state: GameState;
- createdAt: Date;
- startedAt?: Date;
- currentTurn?: string; // Player ID whose turn it is
- websocketRoom: string; // WebSocket room name for real-time updates
-}
-
-export class JoinGameCommandHandler {
- private gameRepository: IGameRepository;
- private redisService: RedisService;
-
- constructor() {
- this.gameRepository = DIContainer.getInstance().gameRepository;
- this.redisService = RedisService.getInstance();
- }
-
- async handle(command: JoinGameCommand): Promise {
- const startTime = performance.now();
-
- try {
- logOther('Joining game', `gameCode: ${command.gameCode}, playerId: ${command.playerId || 'anonymous'}, loginType: ${command.loginType}`);
-
- // Find the game by game code
- const game = await this.gameRepository.findByGameCode(command.gameCode);
- if (!game) {
- throw new Error(`Game with code ${command.gameCode} not found`);
- }
-
- // Generate player ID for public games or use provided one
- // For anonymous players (no playerId), use playerName as the identifier to allow rejoining
- const actualPlayerId = command.playerId || `guest_${command.playerName}`;
-
- // Validate game joinability (authentication/org checks done in router)
- this.validateGameJoinability(game, actualPlayerId, command);
-
- // Add player to database
- const updatedGame = await this.gameRepository.addPlayerToGame(game.id, actualPlayerId);
- if (!updatedGame) {
- throw new Error('Failed to add player to game');
- }
-
- // Update Redis with the new player
- await this.updateGameInRedis(updatedGame, { ...command, playerId: actualPlayerId });
-
- const endTime = performance.now();
- logOther('Player joined game successfully', {
- gameId: game.id,
- gameCode: game.gamecode,
- playerId: actualPlayerId,
- playerCount: updatedGame.players.length,
- maxPlayers: updatedGame.maxplayers,
- loginType: game.logintype,
- executionTime: Math.round(endTime - startTime)
- });
-
- return updatedGame;
-
- } catch (error) {
- const endTime = performance.now();
- logError('Failed to join game', error instanceof Error ? error : new Error(String(error)));
- logOther('Game join failed', {
- gameCode: command.gameCode,
- playerId: command.playerId || 'anonymous',
- loginType: command.loginType,
- executionTime: Math.round(endTime - startTime)
- });
- throw error;
- }
- }
-
- private validateGameJoinability(game: GameAggregate, playerId: string, command: JoinGameCommand): void {
- // Check if game is in waiting state
- if (game.state !== GameState.WAITING) {
- throw new Error('Game is not accepting new players');
- }
-
- // Check if player is already in the game
- if (game.players.includes(playerId)) {
- throw new Error('Player is already in this game');
- }
-
- // Check if game is full
- if (game.players.length >= game.maxplayers) {
- throw new Error('Game is full');
- }
-
- // Note: Login type validation is now handled in the router before reaching this handler
- // This ensures proper authentication and organization membership checks are done first
-
- logOther('Game join validation passed', {
- gameId: game.id,
- gameCode: game.gamecode,
- currentPlayers: game.players.length,
- maxPlayers: game.maxplayers,
- gameState: game.state,
- loginType: game.logintype,
- playerId: playerId,
- isAuthenticated: !!command.playerId
- });
- }
-
- private async updateGameInRedis(game: GameAggregate, command: JoinGameCommand & { playerId: string }): Promise {
- try {
- const redisKey = `game:${game.gamecode}`;
-
- // Get existing game data from Redis or create new
- let gameData: ActiveGameData;
- const existingData = await this.redisService.get(redisKey);
-
- if (existingData) {
- gameData = JSON.parse(existingData) as ActiveGameData;
- } else {
- // Create new game data structure
- gameData = {
- gameId: game.id,
- gameCode: game.gamecode,
- maxPlayers: game.maxplayers,
- currentPlayers: [],
- state: game.state,
- createdAt: game.createdate,
- websocketRoom: `game_${game.gamecode}`
- };
- }
-
- // Add the new player
- const newPlayer: GamePlayerData = {
- playerId: command.playerId,
- playerName: command.playerName,
- joinedAt: new Date(),
- isOnline: true
- };
-
- // Check if player name is already in use by a different player
- const existingPlayerWithName = gameData.currentPlayers.find(
- p => p.playerName === command.playerName && p.playerId !== command.playerId
- );
-
- if (existingPlayerWithName) {
- throw new Error(`Player name "${command.playerName}" is already in use in this game`);
- }
-
- // Update players list (remove if exists, then add)
- gameData.currentPlayers = gameData.currentPlayers.filter(p => p.playerId !== command.playerId);
- gameData.currentPlayers.push(newPlayer);
-
- // Update game state and player count
- gameData.state = game.state;
-
- // Store updated data in Redis with TTL (24 hours)
- await this.redisService.setWithExpiry(redisKey, JSON.stringify(gameData), 24 * 60 * 60);
-
- logOther('Game data updated in Redis', {
- gameId: game.id,
- gameCode: game.gamecode,
- redisKey,
- playerCount: gameData.currentPlayers.length,
- websocketRoom: gameData.websocketRoom,
- playerId: command.playerId
- });
-
- } catch (error) {
- logError('Failed to update game in Redis', error instanceof Error ? error : new Error(String(error)));
- // Don't throw error here - Redis failure shouldn't prevent game join
- logOther('Game join completed despite Redis error', {
- gameId: game.id,
- playerId: command.playerId
- });
- }
- }
-
- async getGameFromRedis(gameCode: string): Promise {
- try {
- const redisKey = `game:${gameCode}`;
- const data = await this.redisService.get(redisKey);
- return data ? JSON.parse(data) as ActiveGameData : null;
- } catch (error) {
- logError('Failed to get game from Redis', error instanceof Error ? error : new Error(String(error)));
- return null;
- }
- }
-
- async removePlayerFromRedis(gameCode: string, playerId: string): Promise {
- try {
- const redisKey = `game:${gameCode}`;
- const existingData = await this.redisService.get(redisKey);
-
- if (existingData) {
- const gameData = JSON.parse(existingData) as ActiveGameData;
- gameData.currentPlayers = gameData.currentPlayers.filter(p => p.playerId !== playerId);
-
- await this.redisService.setWithExpiry(redisKey, JSON.stringify(gameData), 24 * 60 * 60);
- }
- } catch (error) {
- logError('Failed to remove player from Redis', error instanceof Error ? error : new Error(String(error)));
- }
- }
-}
\ No newline at end of file
diff --git a/SerpentRace_Backend/src/Application/Game/commands/StartGameCommand.ts b/SerpentRace_Backend/src/Application/Game/commands/StartGameCommand.ts
deleted file mode 100644
index e10fad32..00000000
--- a/SerpentRace_Backend/src/Application/Game/commands/StartGameCommand.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import { LoginType } from '../../../Domain/Game/GameAggregate';
-
-export interface StartGameCommand {
- deckids: string[]; // Array of deck IDs (3 types, multiple decks per type)
- maxplayers: number; // Maximum number of players
- logintype: LoginType; // How players can join the game
- userid?: string; // Optional user who created the game (becomes game master)
- orgid?: string | null; // Organization ID (for organization games)
-}
\ No newline at end of file
diff --git a/SerpentRace_Backend/src/Application/Game/commands/StartGameCommandHandler.ts b/SerpentRace_Backend/src/Application/Game/commands/StartGameCommandHandler.ts
deleted file mode 100644
index 931f05fe..00000000
--- a/SerpentRace_Backend/src/Application/Game/commands/StartGameCommandHandler.ts
+++ /dev/null
@@ -1,289 +0,0 @@
-import { StartGameCommand } from './StartGameCommand';
-import { GameAggregate, GameDeck, GameCard, DeckType, GameState } from '../../../Domain/Game/GameAggregate';
-import { DeckAggregate } from '../../../Domain/Deck/DeckAggregate';
-import { IGameRepository } from '../../../Domain/IRepository/IGameRepository';
-import { IDeckRepository } from '../../../Domain/IRepository/IDeckRepository';
-import { DIContainer } from '../../Services/DIContainer';
-import { RedisService } from '../../Services/RedisService';
-import { logOther, logError } from '../../Services/Logger';
-import { randomBytes } from 'crypto';
-import { GenerateBoardCommand } from './GenerateBoardCommand';
-
-export interface ActiveGameData {
- gameId: string;
- gameCode: string;
- hostId?: string;
- maxPlayers: number;
- currentPlayers: GamePlayerData[];
- state: GameState;
- createdAt: Date;
- startedAt?: Date;
- currentTurn?: string;
- websocketRoom: string;
-}
-
-export interface GamePlayerData {
- playerId: string;
- playerName?: string;
- joinedAt: Date;
- isOnline: boolean;
- position?: number;
-}
-
-export class StartGameCommandHandler {
- private gameRepository: IGameRepository;
- private deckRepository: IDeckRepository;
- private redisService: RedisService;
-
- constructor() {
- this.gameRepository = DIContainer.getInstance().gameRepository;
- this.deckRepository = DIContainer.getInstance().deckRepository;
- this.redisService = RedisService.getInstance();
- }
-
- async handle(command: StartGameCommand): Promise {
- const startTime = performance.now();
-
- try {
- logOther('Starting game creation', `deckCount: ${command.deckids.length}, maxPlayers: ${command.maxplayers}, loginType: ${command.logintype}`);
-
- // Generate unique game code
- const gamecode = this.generateGameCode();
-
- // Fetch all decks by IDs
- const decks = await this.fetchDecks(command.deckids);
-
- // Validate we have 3 deck types
- this.validateDeckTypes(decks);
-
- // Group decks by type and shuffle cards within each type
- const gamedecks = await this.createShuffledGameDecks(decks);
-
- // Create the game aggregate
- const gameData: Partial = {
- gamecode,
- maxplayers: command.maxplayers,
- logintype: command.logintype,
- createdby: command.userid!,
- orgid: command.orgid || null,
- gamedecks,
- players: [],
- winner: null,
- state: GameState.WAITING,
- startdate: null,
- enddate: null
- };
-
- // Save the game to database
- const savedGame = await this.gameRepository.create(gameData);
-
- // Create Redis object for real-time game management
- await this.createGameInRedis(savedGame, command.userid);
-
- // Trigger async board generation (don't block game creation)
- this.triggerAsyncBoardGeneration(savedGame.id).catch((error: Error) => {
- logError('Async board generation failed', error);
- });
-
- const endTime = performance.now();
- logOther('Game created successfully', `gameId: ${savedGame.id}, gameCode: ${savedGame.gamecode}, executionTime: ${Math.round(endTime - startTime)}ms`);
-
- return savedGame;
-
- } catch (error) {
- const endTime = performance.now();
- logError('Failed to create game', error instanceof Error ? error : new Error(String(error)));
- logOther('Game creation failed', `executionTime: ${Math.round(endTime - startTime)}ms`);
- throw new Error('Failed to start game: ' + (error instanceof Error ? error.message : String(error)));
- }
- }
-
- private generateGameCode(): string {
- // Generate a 6-character alphanumeric game code
- const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
- let result = '';
- const randomBytesArray = randomBytes(6);
-
- for (let i = 0; i < 6; i++) {
- result += chars[randomBytesArray[i] % chars.length];
- }
-
- return result;
- }
-
- private async fetchDecks(deckIds: string[]): Promise {
- const decks: DeckAggregate[] = [];
-
- for (const deckId of deckIds) {
- const deck = await this.deckRepository.findById(deckId);
- if (!deck) {
- throw new Error(`Deck with ID ${deckId} not found`);
- }
- decks.push(deck);
- }
-
- return decks;
- }
-
- private validateDeckTypes(decks: DeckAggregate[]): void {
- const deckTypes = new Set(decks.map(deck => deck.type));
-
- // Check if we have all 3 required deck types (LUCK=0, JOKER=1, QUESTION=2)
- const requiredTypes = [0, 1, 2]; // Based on Type enum in DeckAggregate
- const missingTypes = requiredTypes.filter(type => !deckTypes.has(type));
-
- if (missingTypes.length > 0) {
- throw new Error(`Missing required deck types: ${missingTypes.join(', ')}. Game requires LUCK, JOKER, and QUESTION deck types.`);
- }
-
- logOther('Deck types validation passed', `foundTypes: [${Array.from(deckTypes).join(', ')}]`);
- }
-
- private async createShuffledGameDecks(decks: DeckAggregate[]): Promise {
- // Group decks by type
- const decksByType = new Map();
-
- decks.forEach(deck => {
- if (!decksByType.has(deck.type)) {
- decksByType.set(deck.type, []);
- }
- decksByType.get(deck.type)!.push(deck);
- });
-
- const gamedecks: GameDeck[] = [];
-
- // Process each deck type
- for (const [deckType, typeDecks] of decksByType) {
- // Collect all cards from decks of this type
- const allCards: GameCard[] = [];
-
- typeDecks.forEach(deck => {
- deck.cards.forEach(card => {
- const gameCard: GameCard = {
- cardid: this.generateCardId(),
- question: card.text,
- answer: card.answer || undefined,
- type: card.type, // Include card type for proper processing
- consequence: card.consequence || null,
- played: false,
- playerid: undefined
- };
- allCards.push(gameCard);
- });
- });
-
- // Shuffle all cards of this type
- const shuffledCards = this.shuffleArray(allCards);
-
- // Create game deck for this type
- const gameDeck: GameDeck = {
- deckid: typeDecks[0].id, // Use first deck ID as representative
- decktype: this.mapDeckTypeToGameDeckType(deckType),
- cards: shuffledCards
- };
-
- gamedecks.push(gameDeck);
-
- logOther('Created shuffled game deck', `type: ${deckType}, cardCount: ${shuffledCards.length}, sourceDecks: ${typeDecks.length}`);
- }
-
- return gamedecks;
- }
-
- private mapDeckTypeToGameDeckType(deckType: number): DeckType {
- // Map DeckAggregate.Type to GameAggregate.DeckType
- switch (deckType) {
- case 0: return DeckType.LUCK; // LUCK = 0
- case 1: return DeckType.JOCKER; // JOKER = 1
- case 2: return DeckType.QUEST; // QUESTION = 2
- default: throw new Error(`Unknown deck type: ${deckType}`);
- }
- }
-
- private shuffleArray(array: T[]): T[] {
- const shuffled = [...array];
- for (let i = shuffled.length - 1; i > 0; i--) {
- const j = Math.floor(Math.random() * (i + 1));
- [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
- }
- return shuffled;
- }
-
- private generateCardId(): string {
- return randomBytes(8).toString('hex');
- }
-
- private async createGameInRedis(game: GameAggregate, hostId?: string): Promise {
- try {
- const redisKey = `game:${game.id}`;
-
- const gameData: ActiveGameData = {
- gameId: game.id,
- gameCode: game.gamecode,
- hostId: hostId,
- maxPlayers: game.maxplayers,
- currentPlayers: [],
- state: game.state,
- createdAt: game.createdate,
- websocketRoom: `game_${game.gamecode}`
- };
-
- // Store game data in Redis with TTL (24 hours)
- await this.redisService.setWithExpiry(redisKey, JSON.stringify(gameData), 24 * 60 * 60);
-
- // Create game room for WebSocket connections
- await this.redisService.set(`game_room:${game.gamecode}`, game.id);
-
- logOther('Game created in Redis', {
- gameId: game.id,
- gameCode: game.gamecode,
- hostId: hostId,
- websocketRoom: gameData.websocketRoom,
- redisKey
- });
-
- } catch (error) {
- logError('Failed to create game in Redis', error instanceof Error ? error : new Error(String(error)));
- // Don't throw error here - Redis failure shouldn't prevent game creation
- logOther('Game created successfully despite Redis error', {
- gameId: game.id,
- gameCode: game.gamecode
- });
- }
- }
-
- private async triggerAsyncBoardGeneration(gameId: string): Promise {
- try {
- // Calculate default field counts based on game configuration
- // For now, use reasonable defaults - this should be configurable by host in the future
- const maxSpecialFieldsPercentage = parseInt(process.env.MAX_SPECIAL_FIELDS_PERCENTAGE || '67');
- const maxSpecialFields = Math.floor((100 * maxSpecialFieldsPercentage) / 100);
-
- // Default distribution: 60% positive, 25% negative, 15% luck
- const positiveFieldCount = Math.floor(maxSpecialFields * 0.6);
- const negativeFieldCount = Math.floor(maxSpecialFields * 0.25);
- const luckFieldCount = Math.floor(maxSpecialFields * 0.15);
-
- const command: GenerateBoardCommand = {
- gameId,
- positiveFieldCount,
- negativeFieldCount,
- luckFieldCount
- };
-
- logOther(`Triggering async board generation for game ${gameId}`, {
- positiveFieldCount,
- negativeFieldCount,
- luckFieldCount,
- totalSpecialFields: positiveFieldCount + negativeFieldCount + luckFieldCount
- });
-
- // Execute board generation in background
- await DIContainer.getInstance().generateBoardCommandHandler.execute(command);
-
- } catch (error) {
- logError(`Async board generation failed for game ${gameId}`, error as Error);
- // Don't propagate error - board generation failure shouldn't affect game creation
- }
- }
-}
\ No newline at end of file
diff --git a/SerpentRace_Backend/src/Application/Game/commands/StartGamePlayCommand.ts b/SerpentRace_Backend/src/Application/Game/commands/StartGamePlayCommand.ts
deleted file mode 100644
index af62a030..00000000
--- a/SerpentRace_Backend/src/Application/Game/commands/StartGamePlayCommand.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface StartGamePlayCommand {
- gameId: string; // Game ID to start
- userId?: string; // User who is starting the game (should be game master)
-}
\ No newline at end of file
diff --git a/SerpentRace_Backend/src/Application/Game/commands/StartGamePlayCommandHandler.ts b/SerpentRace_Backend/src/Application/Game/commands/StartGamePlayCommandHandler.ts
deleted file mode 100644
index 6d352403..00000000
--- a/SerpentRace_Backend/src/Application/Game/commands/StartGamePlayCommandHandler.ts
+++ /dev/null
@@ -1,480 +0,0 @@
-import { StartGamePlayCommand } from './StartGamePlayCommand';
-import { GameAggregate, GameState, BoardData, GameField } from '../../../Domain/Game/GameAggregate';
-import { IGameRepository } from '../../../Domain/IRepository/IGameRepository';
-import { DIContainer } from '../../Services/DIContainer';
-import { RedisService } from '../../Services/RedisService';
-import { WebSocketService } from '../../Services/WebSocketService';
-import { logOther, logError } from '../../Services/Logger';
-
-export interface GamePlayerPosition {
- playerId: string;
- playerName?: string;
- position: number; // Board position (starts at 0)
- turnOrder: number; // Random number to determine turn sequence
- isOnline: boolean;
- joinedAt: Date;
-}
-
-export interface ActiveGamePlayData {
- gameId: string;
- gameCode: string;
- hostId?: string;
- maxPlayers: number;
- players: GamePlayerPosition[];
- state: GameState;
- createdAt: Date;
- startedAt: Date;
- currentTurn: number; // Index of current player in turn order
- currentPlayer: string; // ID of the player whose turn it is
- turnSequence: string[]; // Ordered array of player IDs based on turnOrder
- websocketRoom: string;
- gamePhase: 'starting' | 'playing' | 'paused' | 'finished';
- boardData: BoardData; // Generated board with fields
-}
-
-export interface GameStartResult {
- game: GameAggregate;
- boardData: BoardData;
-}
-
-export class StartGamePlayCommandHandler {
- private gameRepository: IGameRepository;
- private redisService: RedisService;
-
- constructor() {
- this.gameRepository = DIContainer.getInstance().gameRepository;
- this.redisService = RedisService.getInstance();
- }
-
- async handle(command: StartGamePlayCommand): Promise {
- const startTime = performance.now();
-
- try {
- logOther('Starting game play', `gameId: ${command.gameId}, userId: ${command.userId || 'system'}`);
-
- // Find the game
- const game = await this.gameRepository.findById(command.gameId);
- if (!game) {
- throw new Error(`Game with ID ${command.gameId} not found`);
- }
-
- // Validate game can be started
- this.validateGameCanStart(game, command.userId);
-
- // Wait for board generation to complete (max 20 seconds)
- const boardData = await this.waitForBoardGeneration(game.id);
-
- // Update game state in database
- const updatedGame = await this.gameRepository.update(game.id, {
- state: GameState.ACTIVE,
- startdate: new Date()
- });
-
- if (!updatedGame) {
- throw new Error('Failed to update game state');
- }
-
- // Initialize game play in Redis with board data
- await this.initializeGamePlayInRedis(updatedGame, boardData);
-
- // Notify all players via WebSocket
- await this.notifyGameStart(updatedGame);
-
- const endTime = performance.now();
- logOther('Game play started successfully', {
- gameId: updatedGame.id,
- gameCode: updatedGame.gamecode,
- playerCount: updatedGame.players.length,
- executionTime: Math.round(endTime - startTime)
- });
-
- return {
- game: updatedGame,
- boardData: boardData
- };
-
- } catch (error) {
- const endTime = performance.now();
- logError('Failed to start game play', error instanceof Error ? error : new Error(String(error)));
- logOther('Game start failed', {
- gameId: command.gameId,
- userId: command.userId,
- executionTime: Math.round(endTime - startTime)
- });
- throw error;
- }
- }
-
- private validateGameCanStart(game: GameAggregate, userId?: string): void {
- // Check if game is in waiting state
- if (game.state !== GameState.WAITING) {
- throw new Error('Game is not in waiting state and cannot be started');
- }
-
- // Check if there are enough players (at least 2)
- if (game.players.length < 2) {
- throw new Error('Game needs at least 2 players to start');
- }
-
- // For private and organization games, check if user is game master
- if (game.createdby && userId && game.createdby !== userId) {
- throw new Error('Only the game master can start this game');
- }
-
- logOther('Game start validation passed', {
- gameId: game.id,
- gameCode: game.gamecode,
- playerCount: game.players.length,
- gameState: game.state,
- isGameMaster: !game.createdby || (userId && game.createdby === userId)
- });
- }
-
- private async initializeGamePlayInRedis(game: GameAggregate, boardData: BoardData): Promise {
- try {
- const redisKey = `gameplay:${game.gamecode}`;
-
- // Get connected player names from Redis (stored by WebSocket)
- const playerNamesMap = await this.getPlayerNames(game.gamecode);
-
- // Generate random turn orders for all players
- const playersWithPositions = this.initializePlayerPositions(game.players, playerNamesMap);
-
- // Sort by turn order to create turn sequence
- const turnSequence = [...playersWithPositions]
- .sort((a, b) => a.turnOrder - b.turnOrder)
- .map(p => p.playerId);
-
- const gamePlayData: ActiveGamePlayData = {
- gameId: game.id,
- gameCode: game.gamecode,
- hostId: game.createdby || undefined,
- maxPlayers: game.maxplayers,
- players: playersWithPositions,
- state: GameState.ACTIVE,
- createdAt: game.createdate,
- startedAt: new Date(),
- currentTurn: 0, // Start with first player in sequence
- currentPlayer: turnSequence[0], // First player in turn sequence
- turnSequence,
- websocketRoom: `game_${game.gamecode}`,
- gamePhase: 'starting',
- boardData
- };
-
- // Store game play data in Redis with TTL (24 hours)
- await this.redisService.setWithExpiry(redisKey, JSON.stringify(gamePlayData), 24 * 60 * 60);
-
- logOther('Game play initialized in Redis', {
- gameId: game.id,
- gameCode: game.gamecode,
- playerCount: playersWithPositions.length,
- turnSequence,
- currentPlayer: turnSequence[0],
- redisKey
- });
-
- } catch (error) {
- logError('Failed to initialize game play in Redis', error instanceof Error ? error : new Error(String(error)));
- throw new Error('Failed to initialize game session');
- }
- }
-
- private initializePlayerPositions(playerIds: string[], playerNamesMap: Map): GamePlayerPosition[] {
- const players: GamePlayerPosition[] = [];
-
- // Generate random turn orders (1 to playerCount)
- const turnOrders = this.generateRandomTurnOrders(playerIds.length);
-
- playerIds.forEach((playerId, index) => {
- players.push({
- playerId,
- playerName: playerNamesMap.get(playerId) || playerId, // Use mapped name or fallback to ID
- position: 0, // All players start at position 0
- turnOrder: turnOrders[index],
- isOnline: true, // Assume online when game starts
- joinedAt: new Date()
- });
- });
-
- logOther('Player positions initialized', {
- playerCount: players.length,
- turnOrders: turnOrders,
- playersData: players.map(p => ({
- playerId: p.playerId,
- playerName: p.playerName,
- position: p.position,
- turnOrder: p.turnOrder
- }))
- });
-
- return players;
- }
-
- private generateRandomTurnOrders(playerCount: number): number[] {
- // Create array [1, 2, 3, ..., playerCount]
- const orders = Array.from({ length: playerCount }, (_, i) => i + 1);
-
- // Fisher-Yates shuffle
- for (let i = orders.length - 1; i > 0; i--) {
- const j = Math.floor(Math.random() * (i + 1));
- [orders[i], orders[j]] = [orders[j], orders[i]];
- }
-
- return orders;
- }
-
- private async notifyGameStart(game: GameAggregate): Promise {
- try {
- // Get game play data from Redis (contains board data)
- const gamePlayData = await this.getGamePlayFromRedis(game.gamecode);
- if (!gamePlayData) {
- logError('Game play data not found in Redis', new Error('Missing game play data'));
- return;
- }
-
- const boardData = gamePlayData.boardData;
- if (!boardData) {
- logError('Board data not found in game play data', new Error('Missing board data'));
- return;
- }
-
- // Get WebSocket service from DIContainer and broadcast game start
- const gameWebSocketService = DIContainer.getInstance().gameWebSocketService;
- await gameWebSocketService.broadcastGameStart(
- game.gamecode,
- boardData,
- gamePlayData.turnSequence,
- game
- );
-
- logOther('Game start notifications sent via WebSocket', {
- gameId: game.id,
- gameCode: game.gamecode,
- playerCount: game.players.length,
- websocketRoom: `game_${game.gamecode}`,
- firstPlayer: gamePlayData.turnSequence[0]
- });
-
- } catch (error) {
- logError('Failed to send game start notifications', error instanceof Error ? error : new Error(String(error)));
- // Don't throw error here - notification failure shouldn't prevent game start
- }
- }
-
- async getGamePlayFromRedis(gameCode: string): Promise {
- try {
- const redisKey = `gameplay:${gameCode}`;
- const data = await this.redisService.get(redisKey);
- return data ? JSON.parse(data) as ActiveGamePlayData : null;
- } catch (error) {
- logError('Failed to get game play from Redis', error instanceof Error ? error : new Error(String(error)));
- return null;
- }
- }
-
- async updatePlayerPosition(gameCode: string, playerId: string, newPosition: number): Promise {
- try {
- const gameData = await this.getGamePlayFromRedis(gameCode);
- if (!gameData) {
- throw new Error('Game session not found');
- }
-
- // Update player position
- const player = gameData.players.find(p => p.playerId === playerId);
- if (player) {
- player.position = newPosition;
-
- // Save back to Redis
- const redisKey = `gameplay:${gameCode}`;
- await this.redisService.setWithExpiry(redisKey, JSON.stringify(gameData), 24 * 60 * 60);
-
- logOther('Player position updated', {
- gameCode,
- playerId,
- newPosition
- });
- }
- } catch (error) {
- logError('Failed to update player position', error instanceof Error ? error : new Error(String(error)));
- throw error;
- }
- }
-
- async getNextPlayer(gameCode: string): Promise {
- try {
- const gameData = await this.getGamePlayFromRedis(gameCode);
- if (!gameData) {
- return null;
- }
-
- const nextTurnIndex = (gameData.currentTurn + 1) % gameData.turnSequence.length;
- return gameData.turnSequence[nextTurnIndex];
- } catch (error) {
- logError('Failed to get next player', error instanceof Error ? error : new Error(String(error)));
- return null;
- }
- }
-
- private async getPlayerNames(gameCode: string): Promise