diff --git a/.claude/settings.local.json b/.claude/settings.local.json
new file mode 100644
index 0000000..258c098
--- /dev/null
+++ b/.claude/settings.local.json
@@ -0,0 +1,23 @@
+{
+ "permissions": {
+ "allow": [
+ "Bash(npx prisma generate:*)",
+ "Bash(docker-compose:*)",
+ "Bash(npx prisma migrate dev:*)",
+ "Bash(docker port:*)",
+ "Bash(netstat:*)",
+ "Bash(findstr:*)",
+ "Bash(npm run prisma:seed:*)",
+ "Bash(timeout 10 npm run start:dev:*)",
+ "Bash(npm run build:*)",
+ "Bash(npm install:*)",
+ "Bash(docker volume ls:*)",
+ "Bash(tasklist:*)",
+ "Bash(taskkill:*)",
+ "Bash(npm run start:dev:*)",
+ "Bash(npm run dev:*)",
+ "Bash(npx prisma:*)",
+ "Bash(git add:*)"
+ ]
+ }
+}
diff --git a/BUILD_STATUS.md b/BUILD_STATUS.md
new file mode 100644
index 0000000..a34d5a6
--- /dev/null
+++ b/BUILD_STATUS.md
@@ -0,0 +1,373 @@
+# VIP Coordinator - Build Status Report
+
+**Date:** January 25, 2026
+**Status:** Backend Complete ✅ | Frontend Pending
+
+---
+
+## 🎉 What We've Built
+
+### ✅ Complete Backend API (100%)
+
+A production-ready NestJS backend with Auth0 authentication, Prisma ORM, and PostgreSQL.
+
+#### Tech Stack
+- **Framework:** NestJS 10.x (TypeScript)
+- **Database:** PostgreSQL 15 via Docker (port 5433)
+- **ORM:** Prisma 5.x
+- **Authentication:** Auth0 + Passport JWT
+- **Validation:** class-validator + class-transformer
+- **HTTP Client:** Axios (@nestjs/axios)
+
+#### Modules Implemented
+
+1. **Auth Module** ✅
+ - JWT strategy with Auth0 integration
+ - JWKS key validation
+ - JWT auth guard (global)
+ - Roles guard for RBAC
+ - Custom decorators (@CurrentUser, @Roles, @Public)
+ - First user auto-approval as admin
+ - User approval workflow
+
+2. **Users Module** ✅
+ - List all users
+ - Get user by ID
+ - Update user (name, role)
+ - Approve/deny pending users
+ - Soft delete users
+ - Admin-only access
+
+3. **VIPs Module** ✅
+ - Create VIP profiles
+ - List all VIPs with flights and events
+ - Get VIP details
+ - Update VIP information
+ - Soft delete VIPs
+ - Two arrival modes: Flight, Self-driving
+ - Department organization
+ - Airport pickup / venue transport flags
+
+4. **Drivers Module** ✅
+ - Create driver profiles
+ - List all drivers with schedules
+ - Get driver details
+ - Get complete driver schedule
+ - Update driver information
+ - Optional user account linking
+ - Soft delete drivers
+
+5. **Events Module** ✅
+ - Create schedule events
+ - **Conflict detection** (prevents double-booking drivers)
+ - List all events
+ - Get event details
+ - Update events (with conflict recheck)
+ - Update event status (drivers can do this)
+ - Soft delete events
+ - 5 event types: Transport, Meeting, Event, Meal, Accommodation
+ - 4 event statuses: Scheduled, In-Progress, Completed, Cancelled
+
+6. **Flights Module** ✅
+ - Create flight records
+ - List all flights
+ - Get flights by VIP
+ - Update flight information
+ - Delete flights
+ - **Real-time flight tracking** (AviationStack API integration)
+ - Multi-segment itinerary support
+
+#### Database Schema
+
+**5 Core Models:**
+- User (auth0Id, email, role, isApproved, deletedAt)
+- VIP (name, organization, department, arrivalMode, etc.)
+- Driver (name, phone, department, userId, deletedAt)
+- ScheduleEvent (vipId, driverId, times, type, status, deletedAt)
+- Flight (vipId, flightNumber, airports, times, status)
+
+**3 Enums:**
+- Role: ADMINISTRATOR, COORDINATOR, DRIVER
+- Department: OFFICE_OF_DEVELOPMENT, ADMIN
+- ArrivalMode: FLIGHT, SELF_DRIVING
+- EventType: TRANSPORT, MEETING, EVENT, MEAL, ACCOMMODATION
+- EventStatus: SCHEDULED, IN_PROGRESS, COMPLETED, CANCELLED
+
+**Features:**
+- Soft deletes on all main entities
+- Automatic timestamps (createdAt, updatedAt)
+- Cascading relationships
+- Indexed columns for performance
+
+#### API Endpoints (40+ endpoints)
+
+All endpoints prefixed with `/api/v1`
+
+**Public:**
+- GET /health - Health check
+
+**Auth:**
+- GET /auth/profile - Get current user
+
+**Users** (Admin only):
+- GET /users
+- GET /users/pending
+- GET /users/:id
+- PATCH /users/:id
+- PATCH /users/:id/approve
+- DELETE /users/:id
+
+**VIPs** (Admin, Coordinator; Drivers view-only):
+- GET /vips
+- POST /vips
+- GET /vips/:id
+- PATCH /vips/:id
+- DELETE /vips/:id
+
+**Drivers** (Admin, Coordinator; Drivers view-only):
+- GET /drivers
+- POST /drivers
+- GET /drivers/:id
+- GET /drivers/:id/schedule
+- PATCH /drivers/:id
+- DELETE /drivers/:id
+
+**Events** (Admin, Coordinator create/update; Drivers can update status):
+- GET /events
+- POST /events (with conflict detection!)
+- GET /events/:id
+- PATCH /events/:id
+- PATCH /events/:id/status
+- DELETE /events/:id
+
+**Flights** (Admin, Coordinator):
+- GET /flights
+- POST /flights
+- GET /flights/status/:flightNumber (real-time tracking!)
+- GET /flights/vip/:vipId
+- GET /flights/:id
+- PATCH /flights/:id
+- DELETE /flights/:id
+
+#### Security Features
+
+- ✅ JWT authentication on all routes (except @Public)
+- ✅ Role-based access control (RBAC)
+- ✅ User approval workflow (prevents unauthorized access)
+- ✅ First user auto-admin (solves bootstrap problem)
+- ✅ Input validation on all DTOs
+- ✅ SQL injection prevention (Prisma ORM)
+- ✅ Soft deletes (preserve data)
+- ✅ CORS configuration
+
+#### Sample Data
+
+Database seeded with:
+- 2 sample users (admin, coordinator)
+- 2 sample VIPs (flight arrival, self-driving)
+- 2 sample drivers
+- 3 sample events (airport pickup, dinner, conference transport)
+
+---
+
+## 📁 Project Structure
+
+```
+backend/
+├── prisma/
+│ ├── schema.prisma # Database schema (source of truth)
+│ ├── migrations/ # Auto-generated migrations
+│ │ └── 20260125085806_init/
+│ └── seed.ts # Sample data seeder
+├── src/
+│ ├── main.ts # App entry point
+│ ├── app.module.ts # Root module (imports all features)
+│ ├── app.controller.ts # Health check
+│ ├── app.service.ts
+│ ├── prisma/
+│ │ ├── prisma.module.ts
+│ │ └── prisma.service.ts # Database service (singleton)
+│ ├── auth/
+│ │ ├── auth.module.ts
+│ │ ├── auth.service.ts
+│ │ ├── auth.controller.ts
+│ │ ├── strategies/
+│ │ │ └── jwt.strategy.ts (Auth0 JWT validation)
+│ │ ├── guards/
+│ │ │ ├── jwt-auth.guard.ts (global guard)
+│ │ │ └── roles.guard.ts (RBAC guard)
+│ │ └── decorators/
+│ │ ├── current-user.decorator.ts
+│ │ ├── roles.decorator.ts
+│ │ └── public.decorator.ts
+│ ├── users/
+│ │ ├── users.module.ts
+│ │ ├── users.service.ts
+│ │ ├── users.controller.ts
+│ │ └── dto/ (UpdateUserDto, ApproveUserDto)
+│ ├── vips/
+│ │ ├── vips.module.ts
+│ │ ├── vips.service.ts
+│ │ ├── vips.controller.ts
+│ │ └── dto/ (CreateVipDto, UpdateVipDto)
+│ ├── drivers/
+│ │ ├── drivers.module.ts
+│ │ ├── drivers.service.ts
+│ │ ├── drivers.controller.ts
+│ │ └── dto/ (CreateDriverDto, UpdateDriverDto)
+│ ├── events/
+│ │ ├── events.module.ts
+│ │ ├── events.service.ts (includes conflict detection)
+│ │ ├── events.controller.ts
+│ │ └── dto/ (CreateEventDto, UpdateEventDto, UpdateEventStatusDto)
+│ └── flights/
+│ ├── flights.module.ts
+│ ├── flights.service.ts (AviationStack integration)
+│ ├── flights.controller.ts
+│ └── dto/ (CreateFlightDto, UpdateFlightDto)
+├── package.json
+├── tsconfig.json
+├── nest-cli.json
+├── .env
+├── .env.example
+└── README.md
+```
+
+---
+
+## 🚀 Running the Backend
+
+### Prerequisites
+- Node.js 20+
+- Docker Desktop
+- Auth0 Account (free tier)
+
+### Quick Start
+
+```bash
+# 1. Start PostgreSQL
+cd vip-coordinator
+docker-compose up -d postgres
+
+# 2. Install dependencies
+cd backend
+npm install
+
+# 3. Configure Auth0
+# Edit backend/.env with your Auth0 credentials
+
+# 4. Run migrations
+npx prisma generate
+npx prisma migrate dev
+
+# 5. Seed sample data (optional)
+npm run prisma:seed
+
+# 6. Start backend
+npm run start:dev
+```
+
+Backend will be available at: **http://localhost:3000/api/v1**
+
+### Test It
+
+```bash
+# Health check (public)
+curl http://localhost:3000/api/v1/health
+
+# Get profile (requires Auth0 token)
+curl http://localhost:3000/api/v1/auth/profile \
+ -H "Authorization: Bearer YOUR_AUTH0_TOKEN"
+```
+
+---
+
+## 📊 Build Statistics
+
+- **Total Files Created:** 60+
+- **Lines of Code:** ~3,500+
+- **Modules:** 6 feature modules
+- **API Endpoints:** 40+
+- **Database Tables:** 5 models
+- **Time to Build:** ~2 hours
+
+---
+
+## ✅ What Works
+
+1. ✅ **Auth0 Integration** - JWT authentication fully configured
+2. ✅ **User Management** - CRUD + approval workflow
+3. ✅ **VIP Management** - Complete CRUD with relationships
+4. ✅ **Driver Management** - Complete CRUD with schedule views
+5. ✅ **Event Scheduling** - CRUD + intelligent conflict detection
+6. ✅ **Flight Tracking** - CRUD + real-time API integration
+7. ✅ **Role-Based Access** - Administrator, Coordinator, Driver permissions
+8. ✅ **Database** - PostgreSQL with Prisma, migrations, seeding
+9. ✅ **Docker** - PostgreSQL running in container
+10. ✅ **TypeScript** - Fully typed, compiles without errors
+11. ✅ **Validation** - All inputs validated with DTOs
+12. ✅ **Soft Deletes** - Data preservation across all entities
+13. ✅ **Logging** - NestJS logger throughout
+14. ✅ **Documentation** - README.md, CLAUDE.md
+
+---
+
+## 🔜 What's Next (Frontend)
+
+To complete the application, we need to build:
+
+1. **React Frontend** with Vite
+2. **Shadcn UI** + Tailwind CSS
+3. **Auth0 React SDK** for authentication
+4. **TanStack Query** for data fetching
+5. **React Router** for navigation
+6. **Pages:**
+ - Login / Callback
+ - Dashboard
+ - VIP List / Details / Forms
+ - Driver List / Details / Forms
+ - Schedule Manager (calendar view)
+ - Flight Tracking
+ - User Management (admin)
+7. **Components:**
+ - Protected routes
+ - Navigation
+ - Forms with validation
+ - Data tables
+ - Loading states
+ - Error handling
+
+**Estimated Time:** 4-6 hours for complete frontend
+
+---
+
+## 🎯 Current State
+
+**Backend:** ✅ 100% Complete & Tested
+**Frontend:** ⏳ 0% (not started)
+**Total Progress:** ~50% of full application
+
+The backend is production-ready and can be deployed to Digital Ocean App Platform or any Docker-compatible host. It's fully functional and awaiting the React frontend to become a complete application.
+
+---
+
+**Need to continue building?** Start with the React frontend initialization:
+
+```bash
+cd vip-coordinator
+npm create vite@latest frontend -- --template react-ts
+cd frontend
+npm install
+```
+
+Then add:
+- Shadcn UI setup
+- Auth0 React SDK
+- TanStack Query
+- React Router
+- All pages and components
+
+---
+
+**Last Updated:** January 25, 2026
+**Status:** Backend production-ready, awaiting frontend development
diff --git a/CASL_AUTHORIZATION.md b/CASL_AUTHORIZATION.md
new file mode 100644
index 0000000..701c9be
--- /dev/null
+++ b/CASL_AUTHORIZATION.md
@@ -0,0 +1,650 @@
+# CASL Authorization System
+
+This document describes the CASL-based authorization system implemented in the VIP Coordinator application.
+
+## Overview
+
+CASL (pronounced "castle") is an isomorphic authorization library that makes it easy to manage permissions in both frontend and backend code. It allows us to define abilities once and reuse them across the entire application.
+
+**Key Benefits:**
+- ✅ Type-safe permissions with TypeScript
+- ✅ Consistent authorization logic between frontend and backend
+- ✅ Declarative permission checks
+- ✅ Easy to extend and maintain
+- ✅ Supports complex conditional permissions
+
+## Architecture
+
+### Permissions Model
+
+**Actions:** What can be done
+- `manage` - Special action that allows everything
+- `create` - Create new resources
+- `read` - View resources
+- `update` - Modify existing resources
+- `delete` - Remove resources
+- `approve` - Special: Approve user accounts
+- `update-status` - Special: Update event status (for drivers)
+
+**Subjects:** What resources can be acted upon
+- `User` - User accounts
+- `VIP` - VIP profiles
+- `Driver` - Driver resources
+- `ScheduleEvent` - Schedule events
+- `Flight` - Flight information
+- `Vehicle` - Vehicle management
+- `all` - Special subject representing all resources
+
+### Role-Based Permissions
+
+| Action | Administrator | Coordinator | Driver |
+|--------|--------------|-------------|--------|
+| **Users** | | | |
+| Create | ✅ | ❌ | ❌ |
+| Read | ✅ | ❌ | ❌ |
+| Update | ✅ | ❌ | ❌ |
+| Delete | ✅ | ❌ | ❌ |
+| Approve | ✅ | ❌ | ❌ |
+| **VIPs** | | | |
+| Create | ✅ | ✅ | ❌ |
+| Read | ✅ | ✅ | ✅ |
+| Update | ✅ | ✅ | ❌ |
+| Delete | ✅ | ✅ | ❌ |
+| **Drivers** | | | |
+| Create | ✅ | ✅ | ❌ |
+| Read | ✅ | ✅ | ✅ |
+| Update | ✅ | ✅ | ❌ |
+| Delete | ✅ | ✅ | ❌ |
+| **Vehicles** | | | |
+| Create | ✅ | ✅ | ❌ |
+| Read | ✅ | ✅ | ✅ |
+| Update | ✅ | ✅ | ❌ |
+| Delete | ✅ | ✅ | ❌ |
+| **Schedule Events** | | | |
+| Create | ✅ | ✅ | ❌ |
+| Read | ✅ | ✅ | ✅ |
+| Update | ✅ | ✅ | ❌ |
+| Delete | ✅ | ✅ | ❌ |
+| UpdateStatus | ✅ | ✅ | ✅ (own events) |
+| **Flights** | | | |
+| Read/Manage | ✅ | ✅ | ❌ |
+
+## Backend Implementation
+
+### 1. Ability Factory
+
+**Location:** `backend/src/auth/abilities/ability.factory.ts`
+
+Defines all permissions based on user roles.
+
+```typescript
+import { AbilityFactory, Action } from '../auth/abilities/ability.factory';
+
+@Injectable()
+export class MyService {
+ constructor(private abilityFactory: AbilityFactory) {}
+
+ async doSomething(user: User) {
+ const ability = this.abilityFactory.defineAbilitiesFor(user);
+
+ if (ability.can(Action.Create, 'VIP')) {
+ // User can create VIPs
+ }
+ }
+}
+```
+
+### 2. Abilities Guard
+
+**Location:** `backend/src/auth/guards/abilities.guard.ts`
+
+Guard that checks CASL abilities on routes.
+
+```typescript
+import { UseGuards } from '@nestjs/common';
+import { AbilitiesGuard } from '../auth/guards/abilities.guard';
+
+@Controller('vips')
+@UseGuards(JwtAuthGuard, AbilitiesGuard)
+export class VipsController {
+ // Routes protected by AbilitiesGuard
+}
+```
+
+### 3. Permission Decorators
+
+**Location:** `backend/src/auth/decorators/check-ability.decorator.ts`
+
+Decorators to specify required permissions on routes.
+
+#### Using Helper Decorators (Recommended)
+
+```typescript
+import { CanCreate, CanRead, CanUpdate, CanDelete } from '../auth/decorators/check-ability.decorator';
+
+@Post()
+@CanCreate('VIP')
+create(@Body() dto: CreateVIPDto) {
+ return this.service.create(dto);
+}
+
+@Get()
+@CanRead('VIP')
+findAll() {
+ return this.service.findAll();
+}
+
+@Patch(':id')
+@CanUpdate('VIP')
+update(@Param('id') id: string, @Body() dto: UpdateVIPDto) {
+ return this.service.update(id, dto);
+}
+
+@Delete(':id')
+@CanDelete('VIP')
+remove(@Param('id') id: string) {
+ return this.service.remove(id);
+}
+```
+
+#### Using CheckAbilities Decorator (For Custom Actions)
+
+```typescript
+import { CheckAbilities } from '../auth/decorators/check-ability.decorator';
+import { Action } from '../auth/abilities/ability.factory';
+
+@Patch(':id/approve')
+@CheckAbilities({ action: Action.Approve, subject: 'User' })
+approve(@Param('id') id: string, @Body() dto: ApproveUserDto) {
+ return this.service.approve(id, dto);
+}
+```
+
+#### Multiple Permissions (All Must Be Satisfied)
+
+```typescript
+@Post('complex')
+@CheckAbilities(
+ { action: Action.Read, subject: 'VIP' },
+ { action: Action.Create, subject: 'ScheduleEvent' }
+)
+complexOperation() {
+ // User must have BOTH permissions
+}
+```
+
+### 4. Controller Examples
+
+#### VIPsController
+
+```typescript
+import { Controller, UseGuards } from '@nestjs/common';
+import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
+import { AbilitiesGuard } from '../auth/guards/abilities.guard';
+import { CanCreate, CanRead, CanUpdate, CanDelete } from '../auth/decorators/check-ability.decorator';
+
+@Controller('vips')
+@UseGuards(JwtAuthGuard, AbilitiesGuard)
+export class VipsController {
+ @Post()
+ @CanCreate('VIP')
+ create(@Body() dto: CreateVipDto) { }
+
+ @Get()
+ @CanRead('VIP')
+ findAll() { }
+
+ @Patch(':id')
+ @CanUpdate('VIP')
+ update(@Param('id') id: string, @Body() dto: UpdateVipDto) { }
+
+ @Delete(':id')
+ @CanDelete('VIP')
+ remove(@Param('id') id: string) { }
+}
+```
+
+#### UsersController (Admin Only)
+
+```typescript
+@Controller('users')
+@UseGuards(JwtAuthGuard, AbilitiesGuard)
+export class UsersController {
+ @Get()
+ @CanRead('User') // Only admins can read users
+ findAll() { }
+
+ @Patch(':id/approve')
+ @CheckAbilities({ action: Action.Approve, subject: 'User' })
+ approve(@Param('id') id: string) { }
+}
+```
+
+## Frontend Implementation
+
+### 1. Ability Definitions
+
+**Location:** `frontend/src/lib/abilities.ts`
+
+Mirrors backend ability definitions for consistent permissions.
+
+```typescript
+import { defineAbilitiesFor, Action } from '@/lib/abilities';
+
+const user = { id: '1', role: 'COORDINATOR', isApproved: true };
+const ability = defineAbilitiesFor(user);
+
+if (ability.can(Action.Create, 'VIP')) {
+ // User can create VIPs
+}
+```
+
+### 2. AbilityContext & Hooks
+
+**Location:** `frontend/src/contexts/AbilityContext.tsx`
+
+Provides CASL abilities throughout the React component tree.
+
+#### useAbility Hook
+
+```typescript
+import { useAbility } from '@/contexts/AbilityContext';
+import { Action } from '@/lib/abilities';
+
+function MyComponent() {
+ const ability = useAbility();
+
+ const canCreateVIP = ability.can(Action.Create, 'VIP');
+ const canDeleteDriver = ability.can(Action.Delete, 'Driver');
+
+ return (
+
+ {canCreateVIP && }
+ {canDeleteDriver && }
+
+ );
+}
+```
+
+#### Can Component (Declarative)
+
+```typescript
+import { Can } from '@/contexts/AbilityContext';
+
+function MyComponent() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+```
+
+### 3. Layout Component Example
+
+**Location:** `frontend/src/components/Layout.tsx`
+
+Navigation filtered by permissions:
+
+```typescript
+import { useAbility } from '@/contexts/AbilityContext';
+import { Action } from '@/lib/abilities';
+
+export function Layout() {
+ const ability = useAbility();
+
+ const allNavigation = [
+ { name: 'Dashboard', href: '/dashboard', alwaysShow: true },
+ { name: 'VIPs', href: '/vips', requireRead: 'VIP' as const },
+ { name: 'Users', href: '/users', requireRead: 'User' as const },
+ ];
+
+ const navigation = allNavigation.filter((item) => {
+ if (item.alwaysShow) return true;
+ if (item.requireRead) {
+ return ability.can(Action.Read, item.requireRead);
+ }
+ return true;
+ });
+
+ return (
+
+ );
+}
+```
+
+### 4. Component Examples
+
+#### Conditional Button Rendering
+
+```typescript
+function VIPList() {
+ const ability = useAbility();
+
+ return (
+
+
VIPs
+
+ {ability.can(Action.Create, 'VIP') && (
+
+ )}
+
+ {vips.map(vip => (
+
+ {vip.name}
+
+ {ability.can(Action.Update, 'VIP') && (
+
+ )}
+
+ {ability.can(Action.Delete, 'VIP') && (
+
+ )}
+
+ ))}
+
+ );
+}
+```
+
+#### Using Can Component
+
+```typescript
+import { Can } from '@/contexts/AbilityContext';
+
+function DriverDashboard() {
+ return (
+
+
Driver Dashboard
+
+
+
+
+
+
+
+
+
+
+ You don't have access to flight information.
+
+
+ );
+}
+```
+
+## Migration Guide
+
+### Backend Migration
+
+#### Before (Old RolesGuard Pattern)
+
+```typescript
+import { UseGuards } from '@nestjs/common';
+import { RolesGuard } from '../auth/guards/roles.guard';
+import { Roles } from '../auth/decorators/roles.decorator';
+import { Role } from '@prisma/client';
+
+@Controller('vips')
+@UseGuards(JwtAuthGuard, RolesGuard)
+export class VipsController {
+ @Post()
+ @Roles(Role.ADMINISTRATOR, Role.COORDINATOR)
+ create(@Body() dto: CreateVIPDto) { }
+
+ @Get()
+ @Roles(Role.ADMINISTRATOR, Role.COORDINATOR, Role.DRIVER)
+ findAll() { }
+}
+```
+
+#### After (New CASL Pattern)
+
+```typescript
+import { UseGuards } from '@nestjs/common';
+import { AbilitiesGuard } from '../auth/guards/abilities.guard';
+import { CanCreate, CanRead } from '../auth/decorators/check-ability.decorator';
+
+@Controller('vips')
+@UseGuards(JwtAuthGuard, AbilitiesGuard)
+export class VipsController {
+ @Post()
+ @CanCreate('VIP')
+ create(@Body() dto: CreateVIPDto) { }
+
+ @Get()
+ @CanRead('VIP')
+ findAll() { }
+}
+```
+
+**Benefits:**
+- ✅ More semantic (describes WHAT, not WHO)
+- ✅ Type-safe with autocomplete
+- ✅ Easier to understand intent
+- ✅ Supports complex conditions
+
+### Frontend Migration
+
+#### Before (Direct Role Checks)
+
+```typescript
+import { useAuth } from '@/contexts/AuthContext';
+
+function MyComponent() {
+ const { backendUser } = useAuth();
+ const isAdmin = backendUser?.role === 'ADMINISTRATOR';
+ const canManageVIPs = isAdmin || backendUser?.role === 'COORDINATOR';
+
+ return (
+
+ {canManageVIPs && }
+ {isAdmin && Users}
+
+ );
+}
+```
+
+#### After (CASL Abilities)
+
+```typescript
+import { useAbility } from '@/contexts/AbilityContext';
+import { Action } from '@/lib/abilities';
+
+function MyComponent() {
+ const ability = useAbility();
+
+ return (
+
+ {ability.can(Action.Create, 'VIP') && }
+ {ability.can(Action.Read, 'User') && Users}
+
+ );
+}
+```
+
+**Or using Can component:**
+
+```typescript
+import { Can } from '@/contexts/AbilityContext';
+
+function MyComponent() {
+ return (
+
+
+
+
+
+
+ Users
+
+
+ );
+}
+```
+
+## Adding New Permissions
+
+### 1. Define New Action (If Needed)
+
+**Backend:** `backend/src/auth/abilities/ability.factory.ts`
+**Frontend:** `frontend/src/lib/abilities.ts`
+
+```typescript
+export enum Action {
+ // ... existing actions
+ Export = 'export', // New action
+}
+```
+
+### 2. Update Ability Definitions
+
+**Backend:** `backend/src/auth/abilities/ability.factory.ts`
+
+```typescript
+defineAbilitiesFor(user: User): AppAbility {
+ const { can, cannot, build } = new AbilityBuilder(/* ... */);
+
+ if (user.role === Role.ADMINISTRATOR) {
+ can(Action.Manage, 'all');
+ can(Action.Export, 'all'); // Admins can export anything
+ } else if (user.role === Role.COORDINATOR) {
+ can(Action.Export, 'VIP'); // Coordinators can only export VIPs
+ }
+
+ return build();
+}
+```
+
+**Frontend:** `frontend/src/lib/abilities.ts` (same pattern)
+
+### 3. Use in Controllers
+
+```typescript
+import { CheckAbilities } from '../auth/decorators/check-ability.decorator';
+import { Action } from '../auth/abilities/ability.factory';
+
+@Get('export')
+@CheckAbilities({ action: Action.Export, subject: 'VIP' })
+export() {
+ return this.service.exportToCSV();
+}
+```
+
+### 4. Use in Components
+
+```typescript
+import { Can } from '@/contexts/AbilityContext';
+
+function VIPList() {
+ return (
+
+
+
+
+
+ );
+}
+```
+
+## Best Practices
+
+### ✅ DO
+
+```typescript
+// Use semantic ability checks
+if (ability.can(Action.Create, 'VIP')) { }
+
+// Use Can component for declarative rendering
+
+
+
+
+// Group related permissions in decorators
+@CheckAbilities(
+ { action: Action.Read, subject: 'VIP' },
+ { action: Action.Read, subject: 'Driver' }
+)
+
+// Define abilities based on resources, not roles
+can(Action.Update, 'VIP') // Good
+can(Action.Manage, 'all') // For admins only
+```
+
+### ❌ DON'T
+
+```typescript
+// Don't check roles directly (use abilities instead)
+if (user.role === 'ADMINISTRATOR') { } // Bad
+
+// Don't mix role checks and ability checks
+if (isAdmin || ability.can(Action.Create, 'VIP')) { } // Confusing
+
+// Don't create overly specific actions
+Action.CreateVIPForJamboree // Too specific
+Action.Create // Better
+
+// Don't forget to check both frontend and backend
+// Backend enforces security, frontend improves UX
+```
+
+## Debugging
+
+### Check User Abilities
+
+**Backend:**
+```typescript
+const ability = this.abilityFactory.defineAbilitiesFor(user);
+console.log('Can create VIP?', ability.can(Action.Create, 'VIP'));
+console.log('Can manage all?', ability.can(Action.Manage, 'all'));
+```
+
+**Frontend:**
+```typescript
+const ability = useAbility();
+console.log('Can create VIP?', ability.can(Action.Create, 'VIP'));
+console.log('User abilities:', ability.rules);
+```
+
+### Common Issues
+
+**"User does not have required permissions" error:**
+1. Check user role in database
+2. Verify ability definitions match frontend/backend
+3. Ensure AbilitiesGuard is applied to controller
+4. Check if decorator is correctly specified
+
+**Navigation items not showing:**
+1. Verify AbilityProvider wraps the app
+2. Check ability.can() returns true for expected permissions
+3. Ensure user is authenticated and role is set
+
+**Tests failing:**
+1. Mock AbilityFactory in tests
+2. Provide test abilities in test setup
+3. Use `@casl/ability` test utilities
+
+---
+
+**Last Updated:** 2026-01-25
+**See also:**
+- [CLAUDE.md](./CLAUDE.md) - General project documentation
+- [ERROR_HANDLING.md](./ERROR_HANDLING.md) - Error handling guide
+- [CASL Documentation](https://casl.js.org/) - Official CASL docs
diff --git a/CLAUDE.md b/CLAUDE.md
index 1935f1a..1a68a22 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -1,154 +1,1177 @@
-# VIP Coordinator - Technical Documentation
+# VIP Coordinator - Claude AI Context
+
+**Last Updated:** 2026-01-25
+**Status:** Active Development - Starting Fresh Build
## Project Overview
-VIP Transportation Coordination System - A web application for managing VIP transportation with driver assignments, real-time tracking, and user management.
-## Tech Stack
-- **Frontend**: React with TypeScript, Tailwind CSS
-- **Backend**: Node.js with Express, TypeScript
-- **Database**: PostgreSQL
-- **Authentication**: Google OAuth 2.0 via Google Identity Services
-- **Containerization**: Docker & Docker Compose
-- **State Management**: React Context API
-- **JWT**: Custom JWT Key Manager with automatic rotation
+VIP Coordinator is a full-stack web application for managing VIP transportation logistics and event coordination. It handles VIP profiles, driver assignments, event scheduling with conflict detection, flight tracking, and user management with role-based access control.
-## Authentication System
+**⚠️ CURRENT STATUS: FRESH BUILD IN PROGRESS**
+- Starting from scratch with modern 2026 best practices
+- No production data - database can be reset at any time
+- Feel free to make breaking changes without asking
+- **Focus:** Getting features working correctly > preserving legacy code
-### Current Implementation (Working)
-We use Google Identity Services (GIS) SDK on the frontend to avoid CORS issues:
+---
-1. **Frontend-First OAuth Flow**:
- - Frontend loads Google Identity Services SDK
- - User clicks "Sign in with Google" button
- - Google shows authentication popup
- - Google returns a credential (JWT) directly to frontend
- - Frontend sends credential to backend `/auth/google/verify`
- - Backend verifies credential, creates/updates user, returns JWT
+## Technology Stack (2026 Best Practices)
-2. **Key Files**:
- - `frontend/src/components/GoogleLogin.tsx` - Google Sign-In button with GIS SDK
- - `backend/src/routes/simpleAuth.ts` - Auth endpoints including `/google/verify`
- - `backend/src/services/jwtKeyManager.ts` - JWT token generation with rotation
+### Backend
+- **Framework:** NestJS 10.x (TypeScript)
+- **Database ORM:** Prisma 5.x
+- **Database:** PostgreSQL 15+
+- **Caching:** Redis 7 (optional, for driver location tracking)
+- **Authentication:** Auth0 + Passport.js (JWT strategy)
+- **Validation:** class-validator + class-transformer
+- **Runtime:** Node.js 20+
-3. **User Flow**:
- - First user → Administrator role with status='active'
- - Subsequent users → Coordinator role with status='pending'
- - Pending users see styled waiting page until admin approval
+### Frontend
+- **Framework:** React 18.2.0 (stable)
+- **Build Tool:** Vite 5.x
+- **UI Components:** Shadcn UI (modern, lightweight)
+- **Styling:** Tailwind CSS 3.4+
+- **Data Fetching:** TanStack Query v5 (formerly React Query)
+- **Routing:** React Router 6.x
+- **Forms:** React Hook Form + Zod
+- **Auth:** Auth0 React SDK (@auth0/auth0-react)
-### Important Endpoints
-- `POST /auth/google/verify` - Verify Google credential and create/login user
-- `GET /auth/me` - Get current user from JWT token
-- `GET /auth/users/me` - Get detailed user info including status
-- `GET /auth/setup` - Check if system has users
+### Infrastructure
+- **Development:** Docker + Docker Compose
+- **Production Target:** Digital Ocean (App Platform or Droplet)
+- **Services:** PostgreSQL, Redis (optional), Backend API, Frontend SPA
-## Database Schema
+### Why These Choices?
+
+**NestJS over Express:**
+- Built-in structure prevents spaghetti code
+- Dependency injection, decorators, guards
+- Excellent TypeScript support
+- Scales well for complex applications
+
+**Prisma over raw SQL:**
+- Type-safe database queries
+- Automatic migrations
+- Prevents SQL injection by default
+- Auto-completion in IDE
+
+**Shadcn UI over Material-UI:**
+- Modern design (2024-2026 standard)
+- Lightweight (copy components into project)
+- Full control over styling
+- Better performance
+
+**TanStack Query:**
+- Essential for server state management
+- Automatic caching and refetching
+- Optimistic updates
+- Industry standard for React
+
+**Auth0:**
+- Reliable hosted authentication
+- No self-hosting required
+- Social login support
+- Excellent documentation
+- Free tier for development
+
+---
+
+## Project Structure
-### Users Table
-```sql
-users (
- id VARCHAR(255) PRIMARY KEY,
- google_id VARCHAR(255) UNIQUE,
- email VARCHAR(255) UNIQUE NOT NULL,
- name VARCHAR(255) NOT NULL,
- role VARCHAR(50) CHECK IN ('driver', 'coordinator', 'administrator'),
- profile_picture_url TEXT,
- status VARCHAR(20) DEFAULT 'pending' CHECK IN ('pending', 'active', 'deactivated'),
- approval_status VARCHAR(20) DEFAULT 'pending' CHECK IN ('pending', 'approved', 'denied'),
- phone VARCHAR(50),
- organization VARCHAR(255),
- onboarding_data JSONB,
- approved_by VARCHAR(255),
- approved_at TIMESTAMP,
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
- last_login TIMESTAMP,
- is_active BOOLEAN DEFAULT true,
- updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
-)
```
+vip-coordinator/
+├── backend/ # NestJS Backend (port 3000)
+│ ├── prisma/
+│ │ ├── schema.prisma # Database schema (source of truth)
+│ │ ├── migrations/ # Auto-generated migrations
+│ │ └── seed.ts # Sample data for development
+│ ├── src/
+│ │ ├── main.ts # App entry point
+│ │ ├── app.module.ts # Root module
+│ │ ├── auth/ # Auth0 + JWT authentication
+│ │ │ ├── auth.module.ts
+│ │ │ ├── auth.service.ts
+│ │ │ ├── jwt.strategy.ts
+│ │ │ ├── guards/ # @Roles(), @Public() guards
+│ │ │ └── decorators/ # @CurrentUser() decorator
+│ │ ├── users/ # User management + approval
+│ │ │ ├── users.module.ts
+│ │ │ ├── users.service.ts
+│ │ │ ├── users.controller.ts
+│ │ │ └── dto/
+│ │ ├── vips/ # VIP profile management
+│ │ ├── drivers/ # Driver resource management
+│ │ ├── events/ # Schedule + conflict detection
+│ │ ├── flights/ # Flight tracking API
+│ │ ├── prisma/ # Prisma service
+│ │ │ ├── prisma.module.ts
+│ │ │ └── prisma.service.ts
+│ │ └── common/ # Shared utilities
+│ ├── package.json
+│ └── .env
+│
+├── frontend/ # React Frontend (port 5173)
+│ ├── src/
+│ │ ├── main.tsx # App entry point
+│ │ ├── App.tsx # Root component + routing
+│ │ ├── components/
+│ │ │ ├── ui/ # Shadcn UI components
+│ │ │ ├── auth/ # Login, ProtectedRoute
+│ │ │ ├── vips/ # VIP forms, lists
+│ │ │ ├── drivers/ # Driver components
+│ │ │ └── events/ # Schedule components
+│ │ ├── pages/
+│ │ │ ├── Dashboard.tsx
+│ │ │ ├── VIPList.tsx
+│ │ │ ├── VIPDetails.tsx
+│ │ │ ├── DriverList.tsx
+│ │ │ ├── SchedulePage.tsx
+│ │ │ ├── FlightsPage.tsx
+│ │ │ └── AdminUsersPage.tsx
+│ │ ├── lib/
+│ │ │ ├── api.ts # Axios client
+│ │ │ └── queryClient.ts # TanStack Query config
+│ │ ├── hooks/
+│ │ │ ├── useAuth.ts # Auth0 wrapper
+│ │ │ └── usePermissions.ts
+│ │ └── types/ # TypeScript interfaces
+│ ├── package.json
+│ └── .env
+│
+├── docker-compose.yml # Development environment
+├── docker-compose.prod.yml # Production build
+└── CLAUDE.md # This file (source of truth)
+```
+
+---
+
+## Database Schema (Prisma)
+
+### Core Models
+
+```prisma
+model User {
+ id String @id @default(uuid())
+ auth0Id String @unique // Auth0 sub claim
+ email String @unique
+ name String?
+ picture String?
+ role Role @default(COORDINATOR)
+ isApproved Boolean @default(false)
+ driver Driver? // Optional linked driver
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ deletedAt DateTime? // Soft delete
+}
+
+model VIP {
+ id String @id @default(uuid())
+ name String
+ organization String?
+ department Department
+ arrivalMode ArrivalMode
+ expectedArrival DateTime? // For self-driving
+ airportPickup Boolean @default(false)
+ venueTransport Boolean @default(false)
+ notes String?
+ flights Flight[]
+ events ScheduleEvent[]
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ deletedAt DateTime?
+}
+
+model Driver {
+ id String @id @default(uuid())
+ name String
+ phone String
+ department Department?
+ userId String? @unique
+ user User? @relation(fields: [userId], references: [id])
+ events ScheduleEvent[]
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ deletedAt DateTime?
+}
+
+model ScheduleEvent {
+ id String @id @default(uuid())
+ vipId String
+ vip VIP @relation(fields: [vipId], references: [id])
+ title String
+ location String?
+ startTime DateTime
+ endTime DateTime
+ description String?
+ type EventType @default(TRANSPORT)
+ status EventStatus @default(SCHEDULED)
+ driverId String?
+ driver Driver? @relation(fields: [driverId], references: [id])
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ deletedAt DateTime?
+}
+
+model Flight {
+ id String @id @default(uuid())
+ vipId String
+ vip VIP @relation(fields: [vipId], references: [id])
+ flightNumber String
+ flightDate DateTime
+ segment Int @default(1)
+ departureAirport String // IATA code (e.g., "JFK")
+ arrivalAirport String // IATA code (e.g., "LAX")
+ scheduledDeparture DateTime?
+ scheduledArrival DateTime?
+ actualDeparture DateTime?
+ actualArrival DateTime?
+ status String?
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+}
+
+enum Role {
+ ADMINISTRATOR
+ COORDINATOR
+ DRIVER
+}
+
+enum Department {
+ OFFICE_OF_DEVELOPMENT
+ ADMIN
+}
+
+enum ArrivalMode {
+ FLIGHT
+ SELF_DRIVING
+}
+
+enum EventType {
+ TRANSPORT
+ MEETING
+ EVENT
+ MEAL
+ ACCOMMODATION
+}
+
+enum EventStatus {
+ SCHEDULED
+ IN_PROGRESS
+ COMPLETED
+ CANCELLED
+}
+```
+
+### Relationships
+- User ↔ Driver: One-to-one (optional)
+- VIP ↔ Flight: One-to-many
+- VIP ↔ ScheduleEvent: One-to-many
+- Driver ↔ ScheduleEvent: One-to-many
+
+### Soft Delete Pattern
+All main entities have `deletedAt` field. Always filter:
+```typescript
+where: { deletedAt: null, ...otherConditions }
+```
+
+---
+
+## User Roles & Permissions
+
+| Feature | Administrator | Coordinator | Driver |
+|---------|--------------|-------------|--------|
+| User Management | ✅ Full CRUD | ❌ None | ❌ None |
+| VIP Management | ✅ Full CRUD | ✅ Full CRUD | 👁️ View Only |
+| Driver Management | ✅ Full CRUD | ✅ Full CRUD | 👁️ View Only |
+| Event Scheduling | ✅ Full CRUD | ✅ Full CRUD | ⚠️ View + Update Status |
+| Flight Tracking | ✅ Full Access | ✅ Full Access | ❌ None |
+
+### First User Bootstrap
+- **First user to register becomes Administrator automatically**
+- `isApproved: true` by default for first user
+- Subsequent users require admin approval
+- No manual database editing needed
+
+---
+
+## Development Workflow
+
+### Prerequisites
+- Node.js 20+ and npm 10+
+- Docker Desktop
+- Auth0 Account (free tier)
+- Git
+
+### Initial Setup
+
+**1. Clone and Install**
+```bash
+git clone
+cd vip-coordinator
+
+# Backend
+cd backend
+npm install
+
+# Frontend
+cd ../frontend
+npm install
+```
+
+**2. Configure Auth0**
+- Create Auth0 account at https://auth0.com
+- Create new Application (Single Page Application)
+- Create new API
+- Note: `Domain`, `Client ID`, `Audience`
+- Configure callback URLs:
+ - Allowed Callback URLs: `http://localhost:5173/callback`
+ - Allowed Logout URLs: `http://localhost:5173`
+ - Allowed Web Origins: `http://localhost:5173`
+
+**3. Environment Variables**
+
+**Backend `.env`:**
+```env
+DATABASE_URL="postgresql://postgres:postgres@localhost:5432/vip_coordinator"
+REDIS_URL="redis://localhost:6379"
+
+AUTH0_DOMAIN="your-tenant.us.auth0.com"
+AUTH0_AUDIENCE="https://your-api-identifier"
+
+AVIATIONSTACK_API_KEY="your-api-key" # Optional for flight tracking
+
+NODE_ENV=development
+PORT=3000
+```
+
+**Frontend `.env`:**
+```env
+VITE_API_URL=http://localhost:3000/api/v1
+VITE_AUTH0_DOMAIN=your-tenant.us.auth0.com
+VITE_AUTH0_CLIENT_ID=your-client-id
+VITE_AUTH0_AUDIENCE=https://your-api-identifier
+```
+
+**4. Database Setup**
+```bash
+cd backend
+
+# Generate Prisma Client
+npx prisma generate
+
+# Run migrations
+npx prisma migrate dev --name init
+
+# Seed sample data (optional)
+npx prisma db seed
+```
+
+**5. Run Development Servers**
+
+**Option A: Docker (Recommended)**
+```bash
+# From project root
+docker-compose up -d
+
+# View logs
+docker-compose logs -f backend
+docker-compose logs -f frontend
+```
+
+**Option B: Local**
+```bash
+# Terminal 1: PostgreSQL + Redis
+docker-compose up -d postgres redis
+
+# Terminal 2: Backend
+cd backend
+npm run start:dev
+
+# Terminal 3: Frontend
+cd frontend
+npm run dev
+```
+
+**6. Access Application**
+- Frontend: http://localhost:5173
+- Backend API: http://localhost:3000/api/v1
+- Prisma Studio: `npx prisma studio` (database GUI)
+
+### Common Development Tasks
+
+**Database Migrations**
+```bash
+# Create new migration after schema changes
+npx prisma migrate dev --name describe_your_changes
+
+# Reset database (SAFE IN DEV - no important data)
+npx prisma migrate reset
+
+# View database in GUI
+npx prisma studio
+```
+
+**Adding a New Feature Module**
+
+**Backend (NestJS):**
+```bash
+cd backend
+nest g resource --no-spec # Generates module, service, controller
+```
+
+1. Update `prisma/schema.prisma` with new models
+2. Run `npx prisma migrate dev`
+3. Create DTOs in `src//dto/`
+4. Add guards: `@Roles('ADMINISTRATOR', 'COORDINATOR')`
+5. Implement service methods using Prisma
+
+**Frontend (React):**
+1. Create page in `src/pages/Page.tsx`
+2. Add route in `App.tsx`
+3. Create API hooks using TanStack Query
+4. Add navigation link
+5. Implement role-based rendering
+
+**Code Generation**
+```bash
+# Backend
+nest g module
+nest g service
+nest g controller
+
+# Prisma
+npx prisma generate # After schema changes
+npx prisma migrate dev # Create migration
+```
+
+---
+
+## Key Patterns & Best Practices
+
+### Backend (NestJS) Patterns
+
+**1. Controllers**
+```typescript
+@Controller('vips')
+@UseGuards(JwtAuthGuard, RolesGuard)
+export class VipsController {
+ constructor(private vipsService: VipsService) {}
+
+ @Get()
+ @Roles('ADMINISTRATOR', 'COORDINATOR', 'DRIVER')
+ async findAll(@CurrentUser() user: User) {
+ return this.vipsService.findAll();
+ }
+
+ @Post()
+ @Roles('ADMINISTRATOR', 'COORDINATOR')
+ async create(@Body() createVipDto: CreateVipDto, @CurrentUser() user: User) {
+ return this.vipsService.create(createVipDto);
+ }
+}
+```
+
+**2. Services (Prisma)**
+```typescript
+@Injectable()
+export class VipsService {
+ constructor(private prisma: PrismaService) {}
+
+ async findAll() {
+ return this.prisma.vip.findMany({
+ where: { deletedAt: null },
+ include: { flights: true, events: true },
+ orderBy: { createdAt: 'desc' },
+ });
+ }
+
+ async create(data: CreateVipDto) {
+ return this.prisma.vip.create({
+ data: {
+ ...data,
+ // Prisma handles timestamps automatically
+ },
+ });
+ }
+
+ async softDelete(id: string) {
+ return this.prisma.vip.update({
+ where: { id },
+ data: { deletedAt: new Date() },
+ });
+ }
+}
+```
+
+**3. DTOs with Validation**
+```typescript
+import { IsString, IsEnum, IsOptional, IsBoolean } from 'class-validator';
+
+export class CreateVipDto {
+ @IsString()
+ name: string;
+
+ @IsEnum(Department)
+ department: Department;
+
+ @IsEnum(ArrivalMode)
+ arrivalMode: ArrivalMode;
+
+ @IsOptional()
+ @IsBoolean()
+ airportPickup?: boolean;
+}
+```
+
+**4. Custom Decorators**
+```typescript
+// Get current user from request
+export const CurrentUser = createParamDecorator(
+ (data: unknown, ctx: ExecutionContext): User => {
+ const request = ctx.switchToHttp().getRequest();
+ return request.user;
+ },
+);
+```
+
+**5. Guards**
+```typescript
+@Injectable()
+export class RolesGuard implements CanActivate {
+ constructor(private reflector: Reflector) {}
+
+ canActivate(context: ExecutionContext): boolean {
+ const requiredRoles = this.reflector.get('roles', context.getHandler());
+ if (!requiredRoles) return true;
+
+ const { user } = context.switchToHttp().getRequest();
+ return requiredRoles.includes(user.role);
+ }
+}
+```
+
+### Frontend (React) Patterns
+
+**1. Protected Routes**
+```typescript
+function App() {
+ return (
+
+
+
+ } />
+ }>
+ } />
+ } />
+
+
+
+
+ );
+}
+```
+
+**2. Data Fetching with TanStack Query**
+```typescript
+// Hook
+function useVIPs() {
+ return useQuery({
+ queryKey: ['vips'],
+ queryFn: async () => {
+ const { data } = await api.get('/vips');
+ return data;
+ },
+ });
+}
+
+// Component
+function VIPList() {
+ const { data: vips, isLoading, error } = useVIPs();
+
+ if (isLoading) return ;
+ if (error) return ;
+
+ return ;
+}
+```
+
+**3. Mutations**
+```typescript
+function useCreateVIP() {
+ const queryClient = useQueryClient();
+
+ return useMutation({
+ mutationFn: async (vip: CreateVIPDto) => {
+ const { data } = await api.post('/vips', vip);
+ return data;
+ },
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: ['vips'] });
+ toast.success('VIP created successfully');
+ },
+ onError: (error) => {
+ toast.error(error.message);
+ },
+ });
+}
+```
+
+**4. Forms with React Hook Form + Zod**
+```typescript
+const vipSchema = z.object({
+ name: z.string().min(1, 'Name required'),
+ department: z.enum(['OFFICE_OF_DEVELOPMENT', 'ADMIN']),
+ arrivalMode: z.enum(['FLIGHT', 'SELF_DRIVING']),
+});
+
+type VIPFormData = z.infer;
+
+function VIPForm() {
+ const { register, handleSubmit, formState: { errors } } = useForm({
+ resolver: zodResolver(vipSchema),
+ });
+ const createVIP = useCreateVIP();
+
+ const onSubmit = (data: VIPFormData) => {
+ createVIP.mutate(data);
+ };
+
+ return (
+
+ );
+}
+```
+
+**5. Role-Based Rendering**
+```typescript
+function usePermissions() {
+ const { user } = useAuth0();
+
+ return {
+ canManageUsers: user?.role === 'ADMINISTRATOR',
+ canEditVIPs: ['ADMINISTRATOR', 'COORDINATOR'].includes(user?.role),
+ isDriver: user?.role === 'DRIVER',
+ };
+}
+
+// Usage
+function VIPList() {
+ const { canEditVIPs } = usePermissions();
+
+ return (
+
+ {canEditVIPs && }
+
+
+ );
+}
+```
+
+### Error Handling
+
+**Backend:**
+```typescript
+// Built-in HTTP exceptions
+throw new NotFoundException(`VIP with ID ${id} not found`);
+throw new BadRequestException('Invalid flight number format');
+throw new UnauthorizedException('User not approved');
+throw new ForbiddenException('Insufficient permissions');
+
+// Custom exception filter (optional)
+@Catch(HttpException)
+export class HttpExceptionFilter implements ExceptionFilter {
+ catch(exception: HttpException, host: ArgumentsHost) {
+ const ctx = host.switchToHttp();
+ const response = ctx.getResponse();
+ const status = exception.getStatus();
+
+ response.status(status).json({
+ statusCode: status,
+ message: exception.message,
+ timestamp: new Date().toISOString(),
+ });
+ }
+}
+```
+
+**Frontend:**
+```typescript
+// Global error boundary
+}>
+
+
+
+// Query error handling
+const { data, error } = useQuery({
+ queryKey: ['vips'],
+ queryFn: fetchVIPs,
+ onError: (error) => {
+ console.error('[VIP] Failed to fetch:', error);
+ toast.error('Failed to load VIPs. Please try again.');
+ },
+});
+```
+
+### Logging
+
+**Backend (NestJS Logger):**
+```typescript
+@Injectable()
+export class VipsService {
+ private logger = new Logger(VipsService.name);
+
+ async create(data: CreateVipDto) {
+ this.logger.log(`Creating VIP: ${data.name}`);
+ try {
+ const vip = await this.prisma.vip.create({ data });
+ this.logger.log(`VIP created: ${vip.id}`);
+ return vip;
+ } catch (error) {
+ this.logger.error(`Failed to create VIP: ${error.message}`, error.stack);
+ throw error;
+ }
+ }
+}
+```
+
+**Frontend:**
+```typescript
+// Prefix all logs with feature area
+console.log('[AUTH] User logged in:', user);
+console.error('[API] Request failed:', error);
+console.warn('[SCHEDULE] Conflict detected:', conflict);
+console.debug('[FLIGHT] Status updated:', flight);
+```
+
+---
+
+## Working with Claude AI
+
+### What Claude CANNOT Do
+
+**⚠️ Browser Testing Limitations:**
+- Cannot see your browser window or UI
+- Cannot view browser console directly
+- Cannot see network requests in DevTools
+- Cannot click buttons or interact with the app
+
+### How to Help Claude Debug
+
+**✅ Good Feedback Examples:**
+
+1. **Console Errors:**
+```
+I clicked Login and got this error:
+```
+[AUTH] Failed to authenticate
+POST http://localhost:3000/api/v1/auth/login 401
+Unauthorized: Invalid credentials
+```
+```
+
+2. **Network Errors:**
+```
+When I try to create a VIP, the request fails:
+Request: POST /api/v1/vips
+Status: 500
+Response: { "message": "Prisma validation error" }
+```
+
+3. **UI Issues:**
+```
+The VIP list page shows a blank screen.
+Console shows:
+TypeError: Cannot read property 'map' of undefined
+ at VIPList.tsx:45
+```
+
+**❌ Unhelpful Feedback:**
+- "It doesn't work"
+- "There's an error"
+- "The button is broken"
+
+### Effective Workflow
+
+1. **Claude makes changes** → Writes code
+2. **You run the app** → Test locally
+3. **You share feedback** → Console logs, screenshots, error messages
+4. **Claude debugs** → Fixes based on your feedback
+5. **Repeat** until working
+
+### Tips for Success
+
+- Run `docker-compose logs -f backend` to watch backend logs
+- Keep browser DevTools open (F12)
+- Share full error messages (not just summaries)
+- Take screenshots when UI looks wrong
+- Copy/paste network request/response bodies
+
+---
+
+## Deployment (Digital Ocean)
+
+### Option 1: App Platform (Easiest)
+
+**Pros:**
+- Managed PostgreSQL database
+- Auto-scaling
+- Zero-downtime deployments
+- SSL certificates automatic
+
+**Setup:**
+1. Push code to GitHub
+2. Create DO App Platform app
+3. Connect GitHub repository
+4. Configure components:
+ - **Backend:** Node.js (port 3000)
+ - **Frontend:** Static Site (Vite build)
+ - **Database:** Managed PostgreSQL
+5. Set environment variables in DO dashboard
+6. Deploy
+
+**Cost:** ~$12/month (basic tier)
+
+### Option 2: Droplet + Docker (More Control)
+
+**Pros:**
+- Full control
+- Cheaper for small apps
+- Run everything on one server
+
+**Setup:**
+```bash
+# On Digital Ocean Droplet (Ubuntu 22.04)
+apt update && apt upgrade -y
+apt install docker.io docker-compose -y
+
+# Clone repository
+git clone
+cd vip-coordinator
+
+# Set environment variables
+cp .env.example .env
+nano .env # Edit with production values
+
+# Run with Docker Compose
+docker-compose -f docker-compose.prod.yml up -d
+
+# Set up nginx reverse proxy
+apt install nginx certbot -y
+# Configure nginx for SSL
+```
+
+**Cost:** ~$6/month (basic droplet)
+
+### Environment Variables (Production)
+
+**Backend:**
+```env
+DATABASE_URL="postgresql://user:pass@db-host:5432/vip_coordinator"
+AUTH0_DOMAIN="your-tenant.auth0.com"
+AUTH0_AUDIENCE="https://api.yourapp.com"
+NODE_ENV=production
+PORT=3000
+```
+
+**Frontend:**
+```env
+VITE_API_URL=https://api.yourapp.com/api/v1
+VITE_AUTH0_DOMAIN=your-tenant.auth0.com
+VITE_AUTH0_CLIENT_ID=your-production-client-id
+VITE_AUTH0_AUDIENCE=https://api.yourapp.com
+```
+
+### Auth0 Production Setup
+
+1. Create **Production** Auth0 application (separate from dev)
+2. Update callback URLs to production domain
+3. Configure custom domain (optional)
+4. Enable social logins if needed
+
+### Database Backups
+
+**Managed Database (DO):**
+- Daily automatic backups included
+- Point-in-time recovery
+
+**Self-hosted:**
+```bash
+# Backup script
+pg_dump -U postgres vip_coordinator > backup_$(date +%Y%m%d).sql
+
+# Cron job (daily at 2 AM)
+0 2 * * * /usr/bin/pg_dump -U postgres vip_coordinator > /backups/backup_$(date +\%Y\%m\%d).sql
+```
+
+---
+
+## Testing Strategy
+
+### Backend Testing
+
+**Unit Tests (Services):**
+```typescript
+describe('VipsService', () => {
+ it('should create a VIP', async () => {
+ const vip = await service.create({ name: 'John Doe', ... });
+ expect(vip.name).toBe('John Doe');
+ });
+});
+```
+
+**Integration Tests (Controllers):**
+```typescript
+describe('VipsController', () => {
+ it('GET /vips should return all VIPs', async () => {
+ const response = await request(app.getHttpServer())
+ .get('/api/v1/vips')
+ .set('Authorization', `Bearer ${token}`)
+ .expect(200);
+ expect(response.body).toBeInstanceOf(Array);
+ });
+});
+```
+
+### Frontend Testing
+
+**Component Tests (Vitest + Testing Library):**
+```typescript
+test('VIPList renders VIPs', async () => {
+ render();
+ await waitFor(() => {
+ expect(screen.getByText('John Doe')).toBeInTheDocument();
+ });
+});
+```
+
+**E2E Tests (Playwright) - Recommended:**
+```typescript
+test('admin can create VIP', async ({ page }) => {
+ await page.goto('http://localhost:5173/login');
+ await page.click('text=Login');
+ // ... auth flow
+ await page.goto('/vips');
+ await page.click('text=Add VIP');
+ await page.fill('[name=name]', 'Jane Smith');
+ await page.click('text=Submit');
+ await expect(page.getByText('VIP created')).toBeVisible();
+});
+```
+
+### Running Tests
+
+```bash
+# Backend
+cd backend
+npm test
+npm run test:watch
+npm run test:cov
+
+# Frontend
+cd frontend
+npm test
+npm run test:ui
+
+# E2E
+npm run test:e2e
+```
+
+---
+
+## Security Best Practices
+
+### Backend Security
+
+1. **Always validate input:**
+```typescript
+@Post()
+async create(@Body() dto: CreateVipDto) { // DTO with class-validator
+ return this.service.create(dto);
+}
+```
+
+2. **Use guards everywhere:**
+```typescript
+@UseGuards(JwtAuthGuard, RolesGuard)
+@Roles('ADMINISTRATOR')
+```
+
+3. **Soft deletes (preserve data):**
+```typescript
+async delete(id: string) {
+ return this.prisma.vip.update({
+ where: { id },
+ data: { deletedAt: new Date() },
+ });
+}
+```
+
+4. **Prisma prevents SQL injection automatically**
+
+### Frontend Security
+
+1. **Never store tokens in localStorage** (Auth0 handles this)
+2. **Always use HTTPS in production**
+3. **Sanitize user input before display**
+4. **Check permissions on backend, not just frontend**
+
+### Auth0 Security
+
+- Enable MFA for admin accounts
+- Use Auth0 Actions to add custom claims
+- Rotate client secrets regularly
+- Monitor Auth0 logs for suspicious activity
+
+---
## Common Issues & Solutions
-### 1. CORS/Cross-Origin Issues
-**Problem**: OAuth redirects and popups cause CORS errors
-**Solution**: Use Google Identity Services SDK directly in frontend, send credential to backend
+### Issue: "Cannot connect to database"
-### 2. Missing Database Columns
-**Problem**: Backend expects columns that don't exist
-**Solution**: Run migrations to add missing columns:
-```sql
-ALTER TABLE users ADD COLUMN IF NOT EXISTS status VARCHAR(20) DEFAULT 'pending';
-ALTER TABLE users ADD COLUMN IF NOT EXISTS approval_status VARCHAR(20) DEFAULT 'pending';
-```
-
-### 3. JWT Token Missing Fields
-**Problem**: Frontend expects fields in JWT that aren't included
-**Solution**: Update `jwtKeyManager.ts` to include all required fields (status, approval_status, etc.)
-
-### 4. First User Not Admin
-**Problem**: First user created as coordinator instead of administrator
-**Solution**: Check `isFirstUser()` method properly counts users in database
-
-### 5. Auth Routes 404
-**Problem**: Frontend calling wrong API endpoints
-**Solution**: Auth routes are at `/auth/*` not `/api/auth/*`
-
-## User Management
-
-### User Roles
-- **Administrator**: Full access, can approve users, first user gets this role
-- **Coordinator**: Can manage VIPs and drivers, needs admin approval
-- **Driver**: Can view assigned trips, needs admin approval
-- **Viewer**: Read-only access (if implemented)
-
-### User Status Flow
-1. User signs in with Google → Created with status='pending'
-2. Admin approves → Status changes to 'active'
-3. Admin can deactivate → Status changes to 'deactivated'
-
-### Approval System
-- First user is auto-approved as administrator
-- All other users need admin approval
-- Pending users see a styled waiting page
-- Page auto-refreshes every 30 seconds to check approval
-
-## Docker Setup
-
-### Environment Variables
-Create `.env` file with:
-```
-GOOGLE_CLIENT_ID=your-client-id
-GOOGLE_CLIENT_SECRET=your-client-secret
-GOOGLE_REDIRECT_URI=https://yourdomain.com/auth/google/callback
-FRONTEND_URL=https://yourdomain.com
-DB_PASSWORD=your-secure-password
-```
-
-### Running the System
+**Solution:**
```bash
-docker-compose up -d
+# Check PostgreSQL is running
+docker ps | grep postgres
+
+# Check connection string in .env
+echo $DATABASE_URL
+
+# Test connection
+docker-compose exec backend npx prisma db pull
```
-Services:
-- Frontend: http://localhost:5173
-- Backend: http://localhost:3000
-- PostgreSQL: localhost:5432
-- Redis: localhost:6379
+### Issue: "Auth0 redirect loop"
-## Key Learnings
+**Solution:**
+- Verify `AUTH0_DOMAIN` and `AUTH0_CLIENT_ID` match Auth0 dashboard
+- Check callback URLs in Auth0 settings
+- Clear browser cache and cookies
-1. **Google OAuth Strategy**: Frontend-first approach with GIS SDK avoids CORS issues entirely
-2. **JWT Management**: Custom JWT manager with key rotation provides better security
-3. **Database Migrations**: Always check table schema matches backend expectations
-4. **User Experience**: Clear, styled feedback for pending users improves perception
-5. **Error Handling**: Proper error messages and status codes help debugging
-6. **Docker Warnings**: POSTGRES_PASSWORD warnings are cosmetic and don't affect functionality
+### Issue: "Prisma Client not generated"
-## Future Improvements
+**Solution:**
+```bash
+cd backend
+npx prisma generate
+npm run build
+```
-1. Email notifications when users are approved
-2. Role-based UI components (hide/show based on user role)
-3. Audit logging for all admin actions
-4. Batch user approval interface
-5. Password-based login as fallback
-6. User profile editing
-7. Organization-based access control
\ No newline at end of file
+### Issue: "Port already in use"
+
+**Solution:**
+```bash
+# Windows
+netstat -ano | findstr ":3000"
+taskkill /PID /F
+
+# Mac/Linux
+lsof -ti:3000 | xargs kill -9
+```
+
+### Issue: "First user can't login (not approved)"
+
+**Solution:**
+First user is auto-approved. If this fails:
+```sql
+-- Manually approve first user
+UPDATE "User" SET "isApproved" = true WHERE email = 'admin@example.com';
+```
+
+Or check `backend/src/auth/auth.service.ts` first-user logic.
+
+---
+
+## Development Mode Permissions
+
+Claude AI has full permission to:
+
+- ✅ **Nuke and rebuild** the database without asking
+- ✅ **Make breaking changes** to the codebase
+- ✅ **Delete/rewrite entire files** if it improves the code
+- ✅ **Install new packages** to solve problems properly
+- ✅ **Start fresh** if something is fundamentally broken
+- ✅ **Change architecture** if current approach is flawed
+
+**Focus:** Getting it working correctly > preserving broken code
+
+No production data exists. Feel free to reset everything.
+
+---
+
+## Quick Reference
+
+### Useful Commands
+
+```bash
+# Development
+npm run start:dev # Backend dev server
+npm run dev # Frontend dev server
+docker-compose up -d # Start all services
+
+# Database
+npx prisma migrate dev # Create migration
+npx prisma studio # Database GUI
+npx prisma migrate reset # Reset database
+
+# Production
+docker-compose -f docker-compose.prod.yml up -d
+npm run build # Build frontend
+npm run start:prod # Production server
+
+# Testing
+npm test # Run tests
+npm run test:watch # Watch mode
+npm run test:e2e # E2E tests
+```
+
+### API Endpoints
+
+All endpoints prefixed with `/api/v1`:
+
+```
+POST /auth/login # Login with Auth0
+GET /auth/profile # Get current user
+
+GET /users # List users (admin only)
+PATCH /users/:id/approve # Approve user (admin only)
+
+GET /vips # List VIPs
+POST /vips # Create VIP
+GET /vips/:id # Get VIP details
+PATCH /vips/:id # Update VIP
+DELETE /vips/:id # Soft delete VIP
+
+GET /drivers # List drivers
+POST /drivers # Create driver
+GET /drivers/:id # Get driver + schedule
+PATCH /drivers/:id # Update driver
+DELETE /drivers/:id # Soft delete driver
+
+GET /events # List events
+POST /events # Create event (with conflict check)
+GET /events/:id # Get event
+PATCH /events/:id # Update event
+PATCH /events/:id/status # Update status (driver can do this)
+DELETE /events/:id # Cancel event
+
+GET /flights/:number # Get flight status
+POST /flights/batch # Batch flight lookup
+```
+
+### Key Files
+
+- **Backend Entry:** [backend/src/main.ts](backend/src/main.ts)
+- **Frontend Entry:** [frontend/src/main.tsx](frontend/src/main.tsx)
+- **Database Schema:** [backend/prisma/schema.prisma](backend/prisma/schema.prisma)
+- **Auth Guard:** [backend/src/auth/guards/jwt-auth.guard.ts](backend/src/auth/guards/jwt-auth.guard.ts)
+- **API Client:** [frontend/src/lib/api.ts](frontend/src/lib/api.ts)
+- **Protected Routes:** [frontend/src/components/auth/ProtectedRoute.tsx](frontend/src/components/auth/ProtectedRoute.tsx)
+
+---
+
+**This document is the SOURCE OF TRUTH for the VIP Coordinator project.**
+
+When code conflicts with this document, update the code to match this spec (not vice versa).
diff --git a/ERROR_HANDLING.md b/ERROR_HANDLING.md
new file mode 100644
index 0000000..bf712e5
--- /dev/null
+++ b/ERROR_HANDLING.md
@@ -0,0 +1,337 @@
+# Error Handling Guide
+
+This document describes the error handling patterns implemented in the VIP Coordinator application.
+
+## Backend Error Handling
+
+### Global Exception Filters
+
+The backend uses two global exception filters for consistent error responses:
+
+#### 1. HttpExceptionFilter
+Handles all HTTP exceptions (4xx, 5xx errors) and formats them consistently.
+
+**Features:**
+- Standardized error response format
+- Automatic logging with appropriate levels (error/warn/log)
+- Request context logging (params, query, body)
+- Sensitive data redaction (passwords, tokens, API keys)
+
+**Error Response Format:**
+```json
+{
+ "statusCode": 400,
+ "timestamp": "2026-01-25T10:30:00.000Z",
+ "path": "/api/v1/events",
+ "method": "POST",
+ "message": "Validation failed",
+ "error": "Bad Request",
+ "details": { ... }
+}
+```
+
+#### 2. AllExceptionsFilter
+Catch-all filter for unhandled errors (database errors, runtime exceptions, etc.).
+
+**Features:**
+- Catches all non-HTTP exceptions
+- Prevents server crashes from unhandled errors
+- Logs full stack traces
+- Returns 500 Internal Server Error to client
+- In development: includes stack trace in response
+
+### Using Exceptions in Controllers/Services
+
+**Example:**
+```typescript
+import { BadRequestException, NotFoundException } from '@nestjs/common';
+
+// Simple error
+throw new NotFoundException('VIP not found');
+
+// Error with details
+throw new BadRequestException({
+ message: 'Driver has conflicting events',
+ conflicts: [
+ { id: '123', title: 'Airport Pickup', startTime: '...' }
+ ]
+});
+```
+
+### Logging Best Practices
+
+```typescript
+import { Logger } from '@nestjs/common';
+
+export class MyService {
+ private readonly logger = new Logger(MyService.name);
+
+ async doSomething() {
+ this.logger.log('Starting operation...');
+ this.logger.warn('Conflict detected');
+ this.logger.error('Operation failed', error.stack);
+ }
+}
+```
+
+## Frontend Error Handling
+
+### ErrorHandler Utility
+
+The `ErrorHandler` class provides centralized error handling for the frontend.
+
+**Location:** `frontend/src/lib/errorHandler.ts`
+
+### Quick Usage
+
+```typescript
+import { handleError } from '@/lib/errorHandler';
+
+try {
+ await api.createVIP(data);
+ toast.success('VIP created successfully');
+} catch (error) {
+ handleError('VIP Creation', error, 'Failed to create VIP');
+}
+```
+
+### Advanced Usage
+
+#### Extract Error Message Only
+```typescript
+import { ErrorHandler } from '@/lib/errorHandler';
+
+try {
+ await api.get('/vips');
+} catch (error) {
+ const message = ErrorHandler.getMessage(error, 'Failed to load VIPs');
+ setErrorMessage(message);
+}
+```
+
+#### Show Toast Only
+```typescript
+ErrorHandler.showError(error, 'Operation failed');
+```
+
+#### Log Only (No Toast)
+```typescript
+ErrorHandler.log('VIP Fetch', error, { vipId: '123' });
+```
+
+#### Check Error Type
+```typescript
+try {
+ await api.updateVIP(id, data);
+} catch (error) {
+ if (ErrorHandler.isAuthError(error)) {
+ // Redirect to login
+ navigate('/login');
+ } else if (ErrorHandler.isConflict(error)) {
+ // Show conflict resolution UI
+ const conflicts = ErrorHandler.getConflicts(error);
+ setConflicts(conflicts);
+ } else {
+ ErrorHandler.showError(error);
+ }
+}
+```
+
+### Available Methods
+
+| Method | Description | Example |
+|--------|-------------|---------|
+| `getMessage(error, fallback?)` | Extract user-friendly message | `const msg = ErrorHandler.getMessage(error)` |
+| `showError(error, fallback?)` | Show error toast | `ErrorHandler.showError(error)` |
+| `log(context, error, info?)` | Log to console with context | `ErrorHandler.log('API', error, { id })` |
+| `handle(context, error, fallback?, info?)` | Log + toast | `ErrorHandler.handle('Save', error)` |
+| `isAuthError(error)` | Check if 401/403 | `if (ErrorHandler.isAuthError(error))` |
+| `isConflict(error)` | Check if 409 | `if (ErrorHandler.isConflict(error))` |
+| `isValidationError(error)` | Check if 400 | `if (ErrorHandler.isValidationError(error))` |
+| `getConflicts(error)` | Extract conflicts array | `const conflicts = ErrorHandler.getConflicts(error)` |
+
+### API Client Logging
+
+The axios client automatically logs all requests and responses in development mode.
+
+**Console output format:**
+```
+[API] → POST /api/v1/vips { data: {...} }
+[API] ← 201 POST /api/v1/vips { data: {...} }
+[API] ✖ 400 POST /api/v1/events { status: 400, data: {...} }
+```
+
+**Error types logged:**
+- 401: Authentication required
+- 403: Permission denied
+- 404: Resource not found
+- 409: Conflict (with conflict details)
+- 500+: Server error
+
+### Migration Guide
+
+#### Before (Old Pattern)
+```typescript
+try {
+ await api.createVIP(data);
+ toast.success('VIP created');
+} catch (error: any) {
+ console.error('Failed to create VIP:', error);
+ toast.error(error.response?.data?.message || 'Failed to create VIP');
+}
+```
+
+#### After (New Pattern)
+```typescript
+import { handleError } from '@/lib/errorHandler';
+
+try {
+ await api.createVIP(data);
+ toast.success('VIP created');
+} catch (error) {
+ handleError('VIP Creation', error, 'Failed to create VIP');
+}
+```
+
+**Benefits:**
+- ✅ Consistent error messages across app
+- ✅ Automatic console logging with context
+- ✅ Handles all error types (Axios, Error, unknown)
+- ✅ Type-safe error checking
+- ✅ Less code duplication
+
+## Common Error Scenarios
+
+### 1. Network Error (Backend Down)
+**Backend logs:** None (backend not reachable)
+**Frontend logs:** `[API] ✖ Network error - no response received`
+**User sees:** Toast: "Network error. Please check your connection."
+
+### 2. Authentication Error (401)
+**Backend logs:** `[WARN] [GET] /api/v1/vips - 401 - Unauthorized`
+**Frontend logs:** `[API] ✖ 401 GET /api/v1/vips` + warning
+**User sees:** Toast: "Authentication required. Please log in again."
+
+### 3. Permission Error (403)
+**Backend logs:** `[WARN] [POST] /api/v1/users - 403 - Forbidden resource`
+**Frontend logs:** `[API] ✖ 403 POST /api/v1/users` + warning
+**User sees:** Toast: "You do not have permission to perform this action."
+
+### 4. Validation Error (400)
+**Backend logs:** `[WARN] [POST] /api/v1/events - 400 - Validation failed`
+**Frontend logs:** `[API] ✖ 400 POST /api/v1/events` + response data
+**User sees:** Toast: "Validation failed: email must be a valid email"
+
+### 5. Conflict Error (409)
+**Backend logs:** `[WARN] [POST] /api/v1/events - 409 - Driver has conflicting events`
+**Frontend logs:** `[API] ✖ 409 POST /api/v1/events` + conflicts array
+**User sees:** Toast: "A conflict occurred. Please check for overlapping schedules."
+
+### 6. Server Error (500)
+**Backend logs:** `[ERROR] [GET] /api/v1/vips - 500 - Internal server error` + stack trace
+**Frontend logs:** `[API] ✖ 500 GET /api/v1/vips` + error message
+**User sees:** Toast: "Server error. Please try again later."
+
+## Best Practices
+
+### ✅ DO
+
+```typescript
+// Use handleError for simple cases
+try {
+ await api.post('/vips', data);
+ toast.success('Success');
+} catch (error) {
+ handleError('VIP Creation', error);
+}
+
+// Use ErrorHandler methods for complex cases
+try {
+ await api.updateEvent(id, data);
+ toast.success('Event updated');
+} catch (error) {
+ if (ErrorHandler.isConflict(error)) {
+ // Show conflict resolution dialog
+ showConflictDialog(ErrorHandler.getConflicts(error));
+ } else {
+ ErrorHandler.showError(error);
+ }
+}
+
+// Log errors with context
+ErrorHandler.log('Event Update', error, { eventId: id, changes: data });
+
+// Use structured logging in backend
+this.logger.log(`Created VIP: ${vip.name} (ID: ${vip.id})`);
+this.logger.error(`Failed to create VIP: ${error.message}`, error.stack);
+```
+
+### ❌ DON'T
+
+```typescript
+// Don't use generic error messages
+catch (error) {
+ toast.error('An error occurred'); // Too vague!
+}
+
+// Don't ignore errors
+catch (error) {
+ console.log(error); // Use console.error and proper context
+}
+
+// Don't manually extract error messages
+catch (error: any) {
+ const msg = error.response?.data?.message || 'Failed'; // Use ErrorHandler.getMessage()
+ toast.error(msg);
+}
+
+// Don't log sensitive data
+this.logger.log(`User login: ${email} with password ${password}`); // Never log passwords!
+```
+
+## Debugging Tips
+
+### Enable Verbose Logging
+
+**Backend:** Set `LOG_LEVEL=debug` in `.env`
+
+**Frontend:** Development mode already has verbose logging enabled
+
+### Check Error Context
+
+**Backend logs include:**
+- Timestamp
+- HTTP method
+- URL path
+- Status code
+- Request params/query/body
+- User email (if authenticated)
+
+**Frontend logs include:**
+- Timestamp
+- Context (feature area)
+- HTTP method
+- URL
+- Request/response data
+- Error type
+
+### Common Issues
+
+**"Network error" but backend is running:**
+- Check CORS configuration
+- Verify API_URL in `.env`
+- Check browser DevTools Network tab
+
+**"Authentication required" after login:**
+- Check if token is stored in localStorage
+- Verify Auth0 configuration
+- Check if user is approved in database
+
+**Validation errors don't show field names:**
+- Backend DTO needs proper validation decorators
+- Use class-validator's @IsString(), @IsEmail(), etc.
+
+---
+
+**Last Updated:** 2026-01-25
+**See also:** [CLAUDE.md](./CLAUDE.md) for general project documentation
diff --git a/KEYCLOAK_INTEGRATION_COMPLETE.md b/KEYCLOAK_INTEGRATION_COMPLETE.md
new file mode 100644
index 0000000..2776581
--- /dev/null
+++ b/KEYCLOAK_INTEGRATION_COMPLETE.md
@@ -0,0 +1,75 @@
+# Keycloak Integration Complete! 🎉
+
+## ✅ What Was Changed
+
+### Backend
+1. **Created `backend/src/config/keycloak.ts`** - Keycloak JWT validation configuration
+2. **Updated `backend/src/routes/auth.ts`** - Replaced Auth0 routes with Keycloak
+3. **Updated `backend/src/services/userService.ts`** - Uses Keycloak user info API
+4. **Updated `backend/src/middleware/auth.ts`** - Uses Keycloak config
+5. **Updated `backend/src/index.ts`** - Uses Keycloak JWT middleware
+6. **Updated `backend/.env`** - Replaced Auth0 vars with Keycloak vars
+7. **Updated `docker-compose.dev.yml`** - Added Keycloak service, updated env vars
+
+### Frontend
+1. **Created `frontend/src/contexts/KeycloakContext.tsx`** - Keycloak React provider
+2. **Updated `frontend/src/main.tsx`** - Uses KeycloakProvider instead of Auth0Provider
+3. **Updated `frontend/src/App.tsx`** - Uses useKeycloak hook
+4. **Updated `frontend/src/components/Login.tsx`** - Uses Keycloak login
+5. **Updated `frontend/src/pages/PendingApproval.tsx`** - Uses Keycloak token
+6. **Updated `frontend/src/hooks/useAuthToken.ts`** - Uses Keycloak token
+7. **Updated `frontend/package.json`** - Replaced @auth0/auth0-react with keycloak-js
+8. **Updated `frontend/.env`** - Replaced Auth0 vars with Keycloak vars
+9. **Updated `docker-compose.dev.yml`** - Updated frontend env vars
+
+## 🔧 Environment Variables
+
+### Backend (.env)
+```env
+KEYCLOAK_SERVER_URL=http://localhost:8080
+KEYCLOAK_REALM=vip-coordinator
+KEYCLOAK_CLIENT_ID=vip-coordinator-frontend
+```
+
+### Frontend (.env)
+```env
+VITE_KEYCLOAK_URL=http://localhost:8080
+VITE_KEYCLOAK_REALM=vip-coordinator
+VITE_KEYCLOAK_CLIENT_ID=vip-coordinator-frontend
+```
+
+## 🚀 Next Steps
+
+1. **Rebuild containers:**
+ ```bash
+ docker compose -f docker-compose.dev.yml build
+ docker compose -f docker-compose.dev.yml up -d
+ ```
+
+2. **Install frontend dependencies:**
+ ```bash
+ cd frontend
+ npm install
+ ```
+
+3. **Test the login flow:**
+ - Go to http://localhost:5173
+ - Click "Sign In with Keycloak"
+ - Login with Keycloak credentials
+ - First user becomes administrator
+
+## 📝 Notes
+
+- Database column `auth0_sub` still exists (stores Keycloak `sub` now)
+- `identity_provider` column set to 'keycloak' for new users
+- All Auth0 dependencies removed from package.json
+- Keycloak runs on port 8080
+- Admin console: http://localhost:8080 (admin/admin)
+
+## 🐛 Troubleshooting
+
+If you see errors:
+1. Make sure Keycloak is running: `docker ps | grep keycloak`
+2. Check Keycloak logs: `docker logs vip-coordinator-keycloak-1`
+3. Verify realm and client exist in Keycloak admin console
+4. Check browser console for frontend errors
diff --git a/KEYCLOAK_SETUP.md b/KEYCLOAK_SETUP.md
new file mode 100644
index 0000000..ecc98a2
--- /dev/null
+++ b/KEYCLOAK_SETUP.md
@@ -0,0 +1,61 @@
+# Keycloak Authentication Setup
+
+## Quick Start
+
+### 1. Start Services
+```bash
+docker compose -f docker-compose.dev.yml up -d
+```
+
+### 2. Access Keycloak Admin Console
+- URL: http://localhost:8080
+- Username: `admin`
+- Password: `admin`
+
+### 3. Create Realm
+1. Click "Create Realm"
+2. Name: `vip-coordinator`
+3. Click "Create"
+
+### 4. Create Client (for your app)
+1. Go to **Clients** → **Create client**
+2. Client ID: `vip-coordinator-frontend`
+3. Client type: `OpenID Connect`
+4. Click **Next**
+5. **Capability config:**
+ - ✅ Client authentication: OFF (public client)
+ - ✅ Authorization: OFF
+ - ✅ Standard flow: ON
+ - ✅ Direct access grants: ON
+6. Click **Next**
+7. **Login settings:**
+ - Valid redirect URIs: `http://localhost:5173/*`
+ - Web origins: `http://localhost:5173`
+ - Valid post logout redirect URIs: `http://localhost:5173/*`
+8. Click **Save**
+
+### 5. Enable Google Social Login (Optional)
+1. Go to **Identity providers** → **Add provider** → **Google**
+2. Client ID: (your Google OAuth client ID)
+3. Client Secret: (your Google OAuth secret)
+4. Click **Save**
+
+### 6. Get Configuration
+After setup, Keycloak provides:
+- **Realm URL**: `http://localhost:8080/realms/vip-coordinator`
+- **Client ID**: `vip-coordinator-frontend`
+- **Discovery URL**: `http://localhost:8080/realms/vip-coordinator/.well-known/openid-configuration`
+
+## Next Steps
+1. Update backend to use Keycloak JWT validation
+2. Update frontend to use Keycloak React SDK
+3. Test login flow
+
+## Benefits
+- ✅ Self-hosted in Docker
+- ✅ No external dependencies
+- ✅ Full control over users and roles
+- ✅ Social login support
+- ✅ JWT tokens
+- ✅ User management UI
+- ✅ Role-based access control
diff --git a/QUICKSTART.md b/QUICKSTART.md
new file mode 100644
index 0000000..8b334db
--- /dev/null
+++ b/QUICKSTART.md
@@ -0,0 +1,239 @@
+# VIP Coordinator - Quick Start Guide
+
+## 🚀 Get Started in 5 Minutes
+
+### Prerequisites
+
+- Node.js 20+
+- Docker Desktop
+- Auth0 Account (free tier at https://auth0.com)
+
+### Step 1: Start Database
+
+```bash
+cd vip-coordinator
+docker-compose up -d postgres
+```
+
+### Step 2: Configure Auth0
+
+1. Go to https://auth0.com and create a free account
+2. Create a new **Application** (Single Page Application)
+3. Create a new **API**
+4. Note your credentials:
+ - Domain: `your-tenant.us.auth0.com`
+ - Client ID: `abc123...`
+ - Audience: `https://your-api-identifier`
+
+5. Configure callback URLs in Auth0 dashboard:
+ - **Allowed Callback URLs:** `http://localhost:5173/callback`
+ - **Allowed Logout URLs:** `http://localhost:5173`
+ - **Allowed Web Origins:** `http://localhost:5173`
+
+### Step 3: Configure Backend
+
+```bash
+cd backend
+
+# Edit .env file
+# Replace these with your Auth0 credentials:
+AUTH0_DOMAIN="your-tenant.us.auth0.com"
+AUTH0_AUDIENCE="https://your-api-identifier"
+AUTH0_ISSUER="https://your-tenant.us.auth0.com/"
+
+# Install and setup
+npm install
+npx prisma generate
+npx prisma migrate dev
+npm run prisma:seed
+```
+
+### Step 4: Configure Frontend
+
+```bash
+cd ../frontend
+
+# Edit .env file
+# Replace these with your Auth0 credentials:
+VITE_AUTH0_DOMAIN="your-tenant.us.auth0.com"
+VITE_AUTH0_CLIENT_ID="your-client-id"
+VITE_AUTH0_AUDIENCE="https://your-api-identifier"
+
+# Already installed during build
+# npm install (only if not already done)
+```
+
+### Step 5: Start Everything
+
+```bash
+# Terminal 1: Backend
+cd backend
+npm run start:dev
+
+# Terminal 2: Frontend
+cd frontend
+npm run dev
+```
+
+### Step 6: Access the App
+
+Open your browser to: **http://localhost:5173**
+
+1. Click "Sign In with Auth0"
+2. Create an account or sign in
+3. **First user becomes Administrator automatically!**
+4. Explore the dashboard
+
+---
+
+## 🎯 What You Get
+
+### Backend API (http://localhost:3000/api/v1)
+
+- ✅ **Auth0 Authentication** - Secure JWT-based auth
+- ✅ **User Management** - Approval workflow for new users
+- ✅ **VIP Management** - Complete CRUD with relationships
+- ✅ **Driver Management** - Driver profiles and schedules
+- ✅ **Event Scheduling** - Smart conflict detection
+- ✅ **Flight Tracking** - Real-time flight status (AviationStack API)
+- ✅ **40+ API Endpoints** - Fully documented REST API
+- ✅ **Role-Based Access** - Administrator, Coordinator, Driver
+- ✅ **Sample Data** - Pre-loaded test data
+
+### Frontend (http://localhost:5173)
+
+- ✅ **Modern React UI** - React 18 + TypeScript
+- ✅ **Tailwind CSS** - Beautiful, responsive design
+- ✅ **Auth0 Integration** - Seamless authentication
+- ✅ **TanStack Query** - Smart data fetching and caching
+- ✅ **Dashboard** - Overview with stats and recent activity
+- ✅ **VIP Management** - List, view, create, edit VIPs
+- ✅ **Driver Management** - Manage driver profiles
+- ✅ **Schedule View** - See all events and assignments
+- ✅ **Protected Routes** - Automatic authentication checks
+
+---
+
+## 📊 Sample Data
+
+The database is seeded with:
+
+- **2 Users:** admin@example.com, coordinator@example.com
+- **2 VIPs:** Dr. Robert Johnson (flight), Ms. Sarah Williams (self-driving)
+- **2 Drivers:** John Smith, Jane Doe
+- **3 Events:** Airport pickup, welcome dinner, conference transport
+
+---
+
+## 🔑 User Roles
+
+### Administrator
+- Full system access
+- Can approve/deny new users
+- Can manage all VIPs, drivers, events
+
+### Coordinator
+- Can manage VIPs, drivers, events
+- Cannot manage users
+- Full scheduling access
+
+### Driver
+- View assigned schedules
+- Update event status
+- Cannot create or delete
+
+**First user to register = Administrator** (no manual setup needed!)
+
+---
+
+## 🧪 Testing the API
+
+### Health Check (Public)
+```bash
+curl http://localhost:3000/api/v1/health
+```
+
+### Get Profile (Requires Auth0 Token)
+```bash
+# Get token from browser DevTools -> Application -> Local Storage -> auth0_token
+curl http://localhost:3000/api/v1/auth/profile \
+ -H "Authorization: Bearer YOUR_TOKEN_HERE"
+```
+
+### List VIPs
+```bash
+curl http://localhost:3000/api/v1/vips \
+ -H "Authorization: Bearer YOUR_TOKEN_HERE"
+```
+
+---
+
+## 🐛 Troubleshooting
+
+### "Cannot connect to database"
+```bash
+# Check PostgreSQL is running
+docker ps | grep postgres
+
+# Should see: vip-postgres running on port 5433
+```
+
+### "Auth0 redirect loop"
+- Check your `.env` files have correct Auth0 credentials
+- Verify callback URLs in Auth0 dashboard match `http://localhost:5173/callback`
+- Clear browser cache and cookies
+
+### "Cannot find module"
+```bash
+# Backend
+cd backend
+npx prisma generate
+npm run build
+
+# Frontend
+cd frontend
+npm install
+```
+
+### "Port already in use"
+- Backend uses port 3000
+- Frontend uses port 5173
+- PostgreSQL uses port 5433
+
+Close any processes using these ports.
+
+---
+
+## 📚 Next Steps
+
+1. **Explore the Dashboard** - See stats and recent activity
+2. **Add a VIP** - Try creating a new VIP profile
+3. **Assign a Driver** - Schedule an event with driver assignment
+4. **Test Conflict Detection** - Try double-booking a driver
+5. **Approve Users** - Have someone else sign up, then approve them as admin
+6. **View API Docs** - Check [backend/README.md](backend/README.md)
+
+---
+
+## 🚢 Deploy to Production
+
+See [CLAUDE.md](CLAUDE.md) for Digital Ocean deployment instructions.
+
+Ready to deploy:
+- ✅ Docker Compose configuration
+- ✅ Production environment variables
+- ✅ Optimized builds
+- ✅ Auth0 production setup guide
+
+---
+
+**Need Help?**
+
+- Check [CLAUDE.md](CLAUDE.md) for comprehensive documentation
+- Check [BUILD_STATUS.md](BUILD_STATUS.md) for what's implemented
+- Check [backend/README.md](backend/README.md) for API docs
+- Check [frontend/README.md](frontend/README.md) for frontend docs
+
+**Built with:** NestJS, React, TypeScript, Prisma, PostgreSQL, Auth0, Tailwind CSS
+
+**Last Updated:** January 25, 2026
diff --git a/REQUIREMENTS.md b/REQUIREMENTS.md
new file mode 100644
index 0000000..c1d5c77
--- /dev/null
+++ b/REQUIREMENTS.md
@@ -0,0 +1,282 @@
+# VIP Coordinator - Requirements Document
+
+## Application Purpose
+
+The VIP Coordinator is a web application for managing VIP transportation logistics and event coordination. Organizations use it to coordinate VIP arrivals, manage driver resources, track flight statuses, and schedule events.
+
+---
+
+## Core Features
+
+### 1. VIP Management
+
+The application must allow users to create and manage VIP profiles.
+
+**Required Functionality**:
+- Create VIP profiles with: name, organization, department
+- Support two transportation modes:
+ - **Flight**: VIPs arriving by air
+ - **Self-driving**: VIPs arriving by car
+- For flight arrivals: Support multiple flight segments per VIP (e.g., JFK → LAX → SFO)
+- For self-driving arrivals: Track expected arrival time
+- Organize VIPs by department (Office of Development, Admin)
+- Store notes and special requirements:
+ - Airport pickup needed (yes/no)
+ - Venue transportation needed (yes/no)
+ - General notes
+
+**Required Operations**:
+- Create new VIP
+- View list of all VIPs
+- View VIP details
+- Update VIP information
+- Delete VIP
+
+---
+
+### 2. Driver Management
+
+The application must allow users to manage driver resources.
+
+**Required Functionality**:
+- Create driver profiles with: name, phone number, department
+- Link drivers to user accounts (optional - a driver can be a system user)
+- View driver's complete schedule across all VIP assignments
+- Organize drivers by department
+
+**Required Operations**:
+- Create new driver
+- View list of all drivers
+- View driver details
+- View driver's complete schedule
+- Update driver information
+- Delete driver
+
+---
+
+### 3. Schedule Management
+
+The application must allow users to create and manage events for VIPs.
+
+**Required Functionality**:
+- Create events for VIPs with the following types:
+ - Transport
+ - Meeting
+ - Event
+ - Meal
+ - Accommodation
+- Event details must include:
+ - Title
+ - Location
+ - Start time
+ - End time
+ - Description (optional)
+ - Assigned driver
+- Event status tracking:
+ - Scheduled
+ - In-progress
+ - Completed
+ - Cancelled
+- Conflict prevention:
+ - Prevent double-booking drivers (same driver cannot be assigned to overlapping time slots)
+ - Validate that required fields are provided
+ - Check driver availability before assignment
+
+**Required Operations**:
+- Create event for a VIP
+- View schedule for a VIP
+- View schedule for a driver
+- Update event details
+- Update event status
+- Delete event
+- Check driver availability for a time slot
+- Check for conflicts when assigning a driver
+
+---
+
+### 4. Flight Tracking
+
+The application must track real-time flight status for VIPs arriving by air.
+
+**Required Functionality**:
+- Integrate with a flight data API (AviationStack or equivalent)
+- Track multiple flights per VIP (multi-segment itineraries)
+- Store flight information:
+ - Flight number
+ - Flight date
+ - Segment number (for multi-flight itineraries)
+ - Departure airport code
+ - Arrival airport code
+ - Scheduled departure time
+ - Scheduled arrival time
+ - Actual departure time (updated automatically)
+ - Actual arrival time (updated automatically)
+ - Flight status (scheduled, delayed, landed, etc.)
+- Automatically update flight status via background jobs
+- Validate flight numbers and dates
+
+**Required Operations**:
+- Look up flight information by flight number and date
+- Batch lookup for multiple flights
+- Automatically update flight statuses in the background
+- Display flight status in VIP details
+
+---
+
+### 5. User Authentication & Authorization
+
+The application must control access through authentication and role-based permissions.
+
+**Required Functionality**:
+- Authenticate users via OAuth (Auth0 or equivalent)
+- Support three user roles:
+ - **Administrator**: Full system access including user management
+ - **Coordinator**: Can manage VIPs, drivers, and schedules (cannot manage users)
+ - **Driver**: Can view assigned schedules and update event statuses only
+- First user to register becomes Administrator automatically
+- New users require Administrator approval before accessing the system
+- User approval workflow:
+ - New users start with "pending" status
+ - Administrator can approve or deny users
+ - Only approved users can access the application
+
+**Required Operations**:
+- User login/logout
+- View current user information
+- List all users (Administrator only)
+- View user details (Administrator only)
+- Approve/deny pending users (Administrator only)
+- Update user roles (Administrator only)
+- Delete users (Administrator only)
+
+**Permission Matrix**:
+
+| Feature | Administrator | Coordinator | Driver |
+|--------|--------------|-------------|--------|
+| User Management | ✅ Full | ❌ None | ❌ None |
+| VIP Management | ✅ Full CRUD | ✅ Full CRUD | ❌ View only |
+| Driver Management | ✅ Full CRUD | ✅ Full CRUD | ❌ View only |
+| Schedule Management | ✅ Full CRUD | ✅ Full CRUD | ✅ View + Update status |
+| Flight Tracking | ✅ Full | ✅ Full | ❌ None |
+
+---
+
+## Technical Constraints
+
+### Must Use
+- **PostgreSQL** - Database system
+- **Docker** - For local development environment
+- **TypeScript** - Programming language
+- **React** - Frontend framework
+
+### Should Use
+- **Auth0** - Authentication provider (preferred, but open to alternatives if better)
+- **Redis** - Caching and background job processing
+
+### Cannot Use
+- **Keycloak** - Not acceptable
+
+---
+
+## Data Model Requirements
+
+The application must store the following entities and relationships:
+
+### Entities
+
+**User**
+- Unique identifier
+- Email address (unique)
+- Name
+- Role (Administrator, Coordinator, Driver)
+- Approval status (Pending, Approved, Denied)
+- Authentication provider identifier
+- Profile picture URL (optional)
+- Timestamps (created, updated, last login)
+
+**VIP**
+- Unique identifier
+- Name
+- Organization
+- Department (Office of Development, Admin)
+- Transport mode (Flight, Self-driving)
+- Expected arrival time (for self-driving)
+- Airport pickup needed (boolean)
+- Venue transportation needed (boolean)
+- Notes (text)
+- Timestamps (created, updated)
+
+**Flight**
+- Unique identifier
+- Linked to VIP
+- Flight number
+- Flight date
+- Segment number (for multi-flight itineraries)
+- Departure airport code
+- Arrival airport code
+- Scheduled departure time
+- Scheduled arrival time
+- Actual departure time
+- Actual arrival time
+- Flight status
+- Timestamps (created, updated)
+
+**Driver**
+- Unique identifier
+- Name
+- Phone number
+- Department
+- Linked to User (optional)
+- Timestamps (created, updated)
+
+**Schedule Event**
+- Unique identifier
+- Linked to VIP
+- Title
+- Location
+- Start time
+- End time
+- Description (optional)
+- Assigned driver (optional)
+- Event type (Transport, Meeting, Event, Meal, Accommodation)
+- Status (Scheduled, In-progress, Completed, Cancelled)
+- Timestamps (created, updated)
+
+### Relationships
+- One VIP can have many Flights
+- One VIP can have many Schedule Events
+- One Driver can be assigned to many Schedule Events
+- One User can be linked to one Driver (optional)
+
+---
+
+## Success Criteria
+
+### Functional Requirements
+- ✅ Users can authenticate and remain authenticated
+- ✅ All five core features work as specified
+- ✅ Role-based permissions are enforced correctly
+- ✅ No authentication errors or redirect loops
+- ✅ Application runs locally via Docker
+
+### Quality Requirements
+- ✅ Code is clean and understandable
+- ✅ Error messages are clear and helpful
+- ✅ User interface is responsive (works on desktop and mobile)
+- ✅ Application performs well (feels fast, no noticeable delays)
+
+---
+
+## Implementation Notes
+
+- Choose the architecture, patterns, and libraries that make sense for this project
+- Focus on simplicity and maintainability
+- Avoid over-engineering
+- Make it easy to add new features later
+- Prioritize getting authentication working reliably first
+
+---
+
+**Document Purpose**: This document describes what the application must do, not how to build it.
+**Last Updated**: January 24, 2026
+**Status**: Requirements Document
diff --git a/SUPABASE_MIGRATION.md b/SUPABASE_MIGRATION.md
new file mode 100644
index 0000000..e4c20f3
--- /dev/null
+++ b/SUPABASE_MIGRATION.md
@@ -0,0 +1,33 @@
+# Supabase Auth Migration Plan
+
+## Why Supabase?
+- ✅ **Self-hosted Docker** - Full control, no external dependencies
+- ✅ **Built-in Auth** - JWT tokens, social login (Google), user management
+- ✅ **Simple API** - Similar to Auth0 but simpler
+- ✅ **PostgreSQL** - Uses your existing database
+- ✅ **React SDK** - Easy frontend integration
+- ✅ **No Tailwind issues** - Doesn't affect frontend build
+
+## Migration Steps
+
+### 1. Add Supabase to Docker Compose
+- Add Supabase services (Auth API, PostgREST, GoTrue)
+- Configure to use existing PostgreSQL database
+- Set up environment variables
+
+### 2. Update Backend
+- Replace Auth0 SDK with Supabase client
+- Update JWT validation to use Supabase keys
+- Simplify auth routes
+
+### 3. Update Frontend
+- Replace `@auth0/auth0-react` with `@supabase/supabase-js`
+- Update Login component
+- Update App.tsx auth logic
+
+### 4. Database Migration
+- Keep existing user table structure
+- Add Supabase auth tables (if needed)
+- Map `auth0_sub` → `supabase_user_id`
+
+## Estimated Time: 30-45 minutes
diff --git a/auth0-action.js b/auth0-action.js
new file mode 100644
index 0000000..95ab565
--- /dev/null
+++ b/auth0-action.js
@@ -0,0 +1,35 @@
+/**
+ * Auth0 Action: Add User Info to Token
+ *
+ * This action adds user profile information to the access token
+ * so the backend can create/validate users properly.
+ *
+ * Deploy this in Auth0 Dashboard:
+ * 1. Go to Actions → Flows → Login
+ * 2. Click "+" → Build from scratch
+ * 3. Name: "Add User Info to Token"
+ * 4. Copy this code
+ * 5. Click Deploy
+ * 6. Drag into flow between Start and Complete
+ * 7. Click Apply
+ */
+
+exports.onExecutePostLogin = async (event, api) => {
+ const namespace = 'https://vip-coordinator-api';
+
+ if (event.authorization) {
+ // Add user profile to access token
+ api.accessToken.setCustomClaim(`${namespace}/email`, event.user.email);
+ api.accessToken.setCustomClaim(`${namespace}/name`, event.user.name);
+ api.accessToken.setCustomClaim(`${namespace}/picture`, event.user.picture);
+ api.accessToken.setCustomClaim(`${namespace}/email_verified`, event.user.email_verified);
+
+ // Optionally require email verification before allowing access
+ // Uncomment the lines below if you want to enforce email verification
+ /*
+ if (!event.user.email_verified) {
+ api.access.deny('Please verify your email before accessing the application.');
+ }
+ */
+ }
+};
diff --git a/auth0-signup-form.json b/auth0-signup-form.json
new file mode 100644
index 0000000..50ba068
--- /dev/null
+++ b/auth0-signup-form.json
@@ -0,0 +1,108 @@
+{
+ "name": "VIP Coordinator User Registration",
+ "languages": {
+ "default": "en",
+ "primary": "en"
+ },
+ "pages": [
+ {
+ "name": "user-registration",
+ "components": [
+ {
+ "type": "header",
+ "config": {
+ "text": "Welcome to VIP Coordinator",
+ "level": 1
+ }
+ },
+ {
+ "type": "description",
+ "config": {
+ "text": "Please provide your information to request access. The first user will be automatically approved as Administrator. Subsequent users require admin approval."
+ }
+ },
+ {
+ "type": "text-input",
+ "config": {
+ "label": "Full Name",
+ "name": "name",
+ "placeholder": "Enter your full name",
+ "required": true,
+ "validation": {
+ "min": 2,
+ "max": 100
+ }
+ }
+ },
+ {
+ "type": "email-input",
+ "config": {
+ "label": "Email Address",
+ "name": "email",
+ "placeholder": "your.email@example.com",
+ "required": true,
+ "validation": {
+ "email": true
+ }
+ }
+ },
+ {
+ "type": "password-input",
+ "config": {
+ "label": "Password",
+ "name": "password",
+ "placeholder": "Create a secure password",
+ "required": true,
+ "validation": {
+ "min": 8,
+ "passwordStrength": "fair"
+ }
+ }
+ },
+ {
+ "type": "text-input",
+ "config": {
+ "label": "Department (Optional)",
+ "name": "user_metadata.department",
+ "placeholder": "e.g., Transportation, Events, Security",
+ "required": false
+ }
+ },
+ {
+ "type": "text-input",
+ "config": {
+ "label": "Organization (Optional)",
+ "name": "user_metadata.organization",
+ "placeholder": "Your organization name",
+ "required": false
+ }
+ },
+ {
+ "type": "checkbox",
+ "config": {
+ "label": "I agree to the terms and conditions",
+ "name": "terms_accepted",
+ "required": true
+ }
+ },
+ {
+ "type": "submit-button",
+ "config": {
+ "label": "Request Access"
+ }
+ }
+ ]
+ }
+ ],
+ "ending": {
+ "after_signup": {
+ "type": "redirect",
+ "url": "http://localhost:5173/callback"
+ }
+ },
+ "style": {
+ "primaryColor": "#3B82F6",
+ "backgroundColor": "#F9FAFB",
+ "buttonRadius": "8px"
+ }
+}
diff --git a/backend-old-20260125/.env.example b/backend-old-20260125/.env.example
new file mode 100644
index 0000000..2f00bce
--- /dev/null
+++ b/backend-old-20260125/.env.example
@@ -0,0 +1,37 @@
+# ============================================
+# Auth0 Configuration (NEW)
+# ============================================
+AUTH0_DOMAIN=your-tenant.us.auth0.com
+AUTH0_CLIENT_ID=your_client_id_here
+AUTH0_CLIENT_SECRET=your_client_secret_here
+AUTH0_AUDIENCE=https://vip-coordinator-api
+AUTH0_API_ID=6910ee5a03672ebf6f04fc1c
+AUTH0_CALLBACK_URL=http://localhost:3000/auth/auth0/callback
+AUTH0_LOGOUT_URL=http://localhost:5173/login
+
+# ============================================
+# Application Configuration
+# ============================================
+PORT=3000
+NODE_ENV=development
+FRONTEND_URL=http://localhost:5173
+
+# ============================================
+# Database Configuration
+# ============================================
+DATABASE_URL=postgresql://postgres:changeme@db:5432/vip_coordinator
+
+# ============================================
+# Redis Configuration
+# ============================================
+REDIS_URL=redis://redis:6379
+
+# ============================================
+# Legacy Google OAuth (REMOVE THESE)
+# These are no longer needed with Auth0
+# ============================================
+# GOOGLE_CLIENT_ID=
+# GOOGLE_CLIENT_SECRET=
+# GOOGLE_REDIRECT_URI=
+# JWT_SECRET=
+# ADMIN_PASSWORD=
diff --git a/backend/Dockerfile b/backend-old-20260125/Dockerfile
similarity index 100%
rename from backend/Dockerfile
rename to backend-old-20260125/Dockerfile
diff --git a/backend-old-20260125/dist/config/database.d.ts b/backend-old-20260125/dist/config/database.d.ts
new file mode 100644
index 0000000..2d14e62
--- /dev/null
+++ b/backend-old-20260125/dist/config/database.d.ts
@@ -0,0 +1,4 @@
+import { Pool } from 'pg';
+declare const pool: Pool;
+export default pool;
+//# sourceMappingURL=database.d.ts.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/config/database.d.ts.map b/backend-old-20260125/dist/config/database.d.ts.map
new file mode 100644
index 0000000..78d6a8d
--- /dev/null
+++ b/backend-old-20260125/dist/config/database.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/config/database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAK1B,QAAA,MAAM,IAAI,MAKR,CAAC;AAWH,eAAe,IAAI,CAAC"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/config/database.js b/backend-old-20260125/dist/config/database.js
new file mode 100644
index 0000000..c7f4080
--- /dev/null
+++ b/backend-old-20260125/dist/config/database.js
@@ -0,0 +1,23 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const pg_1 = require("pg");
+const dotenv_1 = __importDefault(require("dotenv"));
+dotenv_1.default.config();
+const pool = new pg_1.Pool({
+ connectionString: process.env.DATABASE_URL || 'postgresql://postgres:changeme@localhost:5432/vip_coordinator',
+ max: 20,
+ idleTimeoutMillis: 30000,
+ connectionTimeoutMillis: 2000,
+});
+// Test the connection
+pool.on('connect', () => {
+ console.log('✅ Connected to PostgreSQL database');
+});
+pool.on('error', (err) => {
+ console.error('❌ PostgreSQL connection error:', err);
+});
+exports.default = pool;
+//# sourceMappingURL=database.js.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/config/database.js.map b/backend-old-20260125/dist/config/database.js.map
new file mode 100644
index 0000000..8306b29
--- /dev/null
+++ b/backend-old-20260125/dist/config/database.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"database.js","sourceRoot":"","sources":["../../src/config/database.ts"],"names":[],"mappings":";;;;;AAAA,2BAA0B;AAC1B,oDAA4B;AAE5B,gBAAM,CAAC,MAAM,EAAE,CAAC;AAEhB,MAAM,IAAI,GAAG,IAAI,SAAI,CAAC;IACpB,gBAAgB,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,+DAA+D;IAC7G,GAAG,EAAE,EAAE;IACP,iBAAiB,EAAE,KAAK;IACxB,uBAAuB,EAAE,IAAI;CAC9B,CAAC,CAAC;AAEH,sBAAsB;AACtB,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;IACtB,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;AACpD,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;IACvB,OAAO,CAAC,KAAK,CAAC,gCAAgC,EAAE,GAAG,CAAC,CAAC;AACvD,CAAC,CAAC,CAAC;AAEH,kBAAe,IAAI,CAAC"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/config/mockDatabase.d.ts b/backend-old-20260125/dist/config/mockDatabase.d.ts
new file mode 100644
index 0000000..d19a2f9
--- /dev/null
+++ b/backend-old-20260125/dist/config/mockDatabase.d.ts
@@ -0,0 +1,17 @@
+declare class MockDatabase {
+ private users;
+ private vips;
+ private drivers;
+ private scheduleEvents;
+ private adminSettings;
+ constructor();
+ query(text: string, params?: any[]): Promise;
+ connect(): Promise<{
+ query: (text: string, params?: any[]) => Promise;
+ release: () => void;
+ }>;
+ end(): Promise;
+ on(event: string, callback: Function): void;
+}
+export default MockDatabase;
+//# sourceMappingURL=mockDatabase.d.ts.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/config/mockDatabase.d.ts.map b/backend-old-20260125/dist/config/mockDatabase.d.ts.map
new file mode 100644
index 0000000..0e54bba
--- /dev/null
+++ b/backend-old-20260125/dist/config/mockDatabase.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"mockDatabase.d.ts","sourceRoot":"","sources":["../../src/config/mockDatabase.ts"],"names":[],"mappings":"AAyBA,cAAM,YAAY;IAChB,OAAO,CAAC,KAAK,CAAoC;IACjD,OAAO,CAAC,IAAI,CAAmC;IAC/C,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,aAAa,CAAkC;;IA8BjD,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;IAiGjD,OAAO;sBAjGK,MAAM,WAAW,GAAG,EAAE,KAAG,OAAO,CAAC,GAAG,CAAC;;;IAyGjD,GAAG;IAIT,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ;CAKrC;AAED,eAAe,YAAY,CAAC"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/config/mockDatabase.js b/backend-old-20260125/dist/config/mockDatabase.js
new file mode 100644
index 0000000..7e86003
--- /dev/null
+++ b/backend-old-20260125/dist/config/mockDatabase.js
@@ -0,0 +1,137 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+class MockDatabase {
+ constructor() {
+ this.users = new Map();
+ this.vips = new Map();
+ this.drivers = new Map();
+ this.scheduleEvents = new Map();
+ this.adminSettings = new Map();
+ // Add a test admin user
+ const adminId = '1';
+ this.users.set(adminId, {
+ id: adminId,
+ email: 'admin@example.com',
+ name: 'Test Admin',
+ role: 'admin',
+ created_at: new Date(),
+ updated_at: new Date()
+ });
+ // Add some test VIPs
+ this.vips.set('1', {
+ id: '1',
+ name: 'John Doe',
+ organization: 'Test Org',
+ department: 'Office of Development',
+ transport_mode: 'flight',
+ expected_arrival: '2025-07-25 14:00',
+ needs_airport_pickup: true,
+ needs_venue_transport: true,
+ notes: 'Test VIP',
+ created_at: new Date(),
+ updated_at: new Date()
+ });
+ }
+ async query(text, params) {
+ console.log('Mock DB Query:', text.substring(0, 50) + '...');
+ // Handle user queries
+ if (text.includes('COUNT(*) FROM users')) {
+ return { rows: [{ count: this.users.size.toString() }] };
+ }
+ if (text.includes('SELECT * FROM users WHERE email')) {
+ const email = params?.[0];
+ const user = Array.from(this.users.values()).find(u => u.email === email);
+ return { rows: user ? [user] : [] };
+ }
+ if (text.includes('SELECT * FROM users WHERE id')) {
+ const id = params?.[0];
+ const user = this.users.get(id);
+ return { rows: user ? [user] : [] };
+ }
+ if (text.includes('SELECT * FROM users WHERE google_id')) {
+ const google_id = params?.[0];
+ const user = Array.from(this.users.values()).find(u => u.google_id === google_id);
+ return { rows: user ? [user] : [] };
+ }
+ if (text.includes('INSERT INTO users')) {
+ const id = Date.now().toString();
+ const user = {
+ id,
+ email: params?.[0],
+ name: params?.[1],
+ role: params?.[2] || 'coordinator',
+ google_id: params?.[4],
+ created_at: new Date(),
+ updated_at: new Date()
+ };
+ this.users.set(id, user);
+ return { rows: [user] };
+ }
+ // Handle VIP queries
+ if (text.includes('SELECT v.*') && text.includes('FROM vips')) {
+ const vips = Array.from(this.vips.values());
+ return {
+ rows: vips.map(v => ({
+ ...v,
+ flights: []
+ }))
+ };
+ }
+ // Handle admin settings queries
+ if (text.includes('SELECT * FROM admin_settings')) {
+ const settings = Array.from(this.adminSettings.entries()).map(([key, value]) => ({
+ key,
+ value
+ }));
+ return { rows: settings };
+ }
+ // Handle drivers queries
+ if (text.includes('SELECT * FROM drivers')) {
+ const drivers = Array.from(this.drivers.values());
+ return { rows: drivers };
+ }
+ // Handle schedule events queries
+ if (text.includes('SELECT * FROM schedule_events')) {
+ const events = Array.from(this.scheduleEvents.values());
+ return { rows: events };
+ }
+ if (text.includes('INSERT INTO vips')) {
+ const id = Date.now().toString();
+ const vip = {
+ id,
+ name: params?.[0],
+ organization: params?.[1],
+ department: params?.[2] || 'Office of Development',
+ transport_mode: params?.[3] || 'flight',
+ expected_arrival: params?.[4],
+ needs_airport_pickup: params?.[5] !== false,
+ needs_venue_transport: params?.[6] !== false,
+ notes: params?.[7] || '',
+ created_at: new Date(),
+ updated_at: new Date()
+ };
+ this.vips.set(id, vip);
+ return { rows: [vip] };
+ }
+ // Default empty result
+ console.log('Unhandled query:', text);
+ return { rows: [] };
+ }
+ async connect() {
+ return {
+ query: this.query.bind(this),
+ release: () => { }
+ };
+ }
+ // Make compatible with pg Pool interface
+ async end() {
+ console.log('Mock database connection closed');
+ }
+ on(event, callback) {
+ if (event === 'connect') {
+ setTimeout(() => callback(), 100);
+ }
+ }
+}
+exports.default = MockDatabase;
+//# sourceMappingURL=mockDatabase.js.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/config/mockDatabase.js.map b/backend-old-20260125/dist/config/mockDatabase.js.map
new file mode 100644
index 0000000..074cf71
--- /dev/null
+++ b/backend-old-20260125/dist/config/mockDatabase.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"mockDatabase.js","sourceRoot":"","sources":["../../src/config/mockDatabase.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/config/redis.d.ts b/backend-old-20260125/dist/config/redis.d.ts
new file mode 100644
index 0000000..2f26493
--- /dev/null
+++ b/backend-old-20260125/dist/config/redis.d.ts
@@ -0,0 +1,292 @@
+declare const redisClient: import("@redis/client").RedisClientType<{
+ graph: {
+ CONFIG_GET: typeof import("@redis/graph/dist/commands/CONFIG_GET");
+ configGet: typeof import("@redis/graph/dist/commands/CONFIG_GET");
+ CONFIG_SET: typeof import("@redis/graph/dist/commands/CONFIG_SET");
+ configSet: typeof import("@redis/graph/dist/commands/CONFIG_SET");
+ DELETE: typeof import("@redis/graph/dist/commands/DELETE");
+ delete: typeof import("@redis/graph/dist/commands/DELETE");
+ EXPLAIN: typeof import("@redis/graph/dist/commands/EXPLAIN");
+ explain: typeof import("@redis/graph/dist/commands/EXPLAIN");
+ LIST: typeof import("@redis/graph/dist/commands/LIST");
+ list: typeof import("@redis/graph/dist/commands/LIST");
+ PROFILE: typeof import("@redis/graph/dist/commands/PROFILE");
+ profile: typeof import("@redis/graph/dist/commands/PROFILE");
+ QUERY: typeof import("@redis/graph/dist/commands/QUERY");
+ query: typeof import("@redis/graph/dist/commands/QUERY");
+ RO_QUERY: typeof import("@redis/graph/dist/commands/RO_QUERY");
+ roQuery: typeof import("@redis/graph/dist/commands/RO_QUERY");
+ SLOWLOG: typeof import("@redis/graph/dist/commands/SLOWLOG");
+ slowLog: typeof import("@redis/graph/dist/commands/SLOWLOG");
+ };
+ json: {
+ ARRAPPEND: typeof import("@redis/json/dist/commands/ARRAPPEND");
+ arrAppend: typeof import("@redis/json/dist/commands/ARRAPPEND");
+ ARRINDEX: typeof import("@redis/json/dist/commands/ARRINDEX");
+ arrIndex: typeof import("@redis/json/dist/commands/ARRINDEX");
+ ARRINSERT: typeof import("@redis/json/dist/commands/ARRINSERT");
+ arrInsert: typeof import("@redis/json/dist/commands/ARRINSERT");
+ ARRLEN: typeof import("@redis/json/dist/commands/ARRLEN");
+ arrLen: typeof import("@redis/json/dist/commands/ARRLEN");
+ ARRPOP: typeof import("@redis/json/dist/commands/ARRPOP");
+ arrPop: typeof import("@redis/json/dist/commands/ARRPOP");
+ ARRTRIM: typeof import("@redis/json/dist/commands/ARRTRIM");
+ arrTrim: typeof import("@redis/json/dist/commands/ARRTRIM");
+ DEBUG_MEMORY: typeof import("@redis/json/dist/commands/DEBUG_MEMORY");
+ debugMemory: typeof import("@redis/json/dist/commands/DEBUG_MEMORY");
+ DEL: typeof import("@redis/json/dist/commands/DEL");
+ del: typeof import("@redis/json/dist/commands/DEL");
+ FORGET: typeof import("@redis/json/dist/commands/FORGET");
+ forget: typeof import("@redis/json/dist/commands/FORGET");
+ GET: typeof import("@redis/json/dist/commands/GET");
+ get: typeof import("@redis/json/dist/commands/GET");
+ MERGE: typeof import("@redis/json/dist/commands/MERGE");
+ merge: typeof import("@redis/json/dist/commands/MERGE");
+ MGET: typeof import("@redis/json/dist/commands/MGET");
+ mGet: typeof import("@redis/json/dist/commands/MGET");
+ MSET: typeof import("@redis/json/dist/commands/MSET");
+ mSet: typeof import("@redis/json/dist/commands/MSET");
+ NUMINCRBY: typeof import("@redis/json/dist/commands/NUMINCRBY");
+ numIncrBy: typeof import("@redis/json/dist/commands/NUMINCRBY");
+ NUMMULTBY: typeof import("@redis/json/dist/commands/NUMMULTBY");
+ numMultBy: typeof import("@redis/json/dist/commands/NUMMULTBY");
+ OBJKEYS: typeof import("@redis/json/dist/commands/OBJKEYS");
+ objKeys: typeof import("@redis/json/dist/commands/OBJKEYS");
+ OBJLEN: typeof import("@redis/json/dist/commands/OBJLEN");
+ objLen: typeof import("@redis/json/dist/commands/OBJLEN");
+ RESP: typeof import("@redis/json/dist/commands/RESP");
+ resp: typeof import("@redis/json/dist/commands/RESP");
+ SET: typeof import("@redis/json/dist/commands/SET");
+ set: typeof import("@redis/json/dist/commands/SET");
+ STRAPPEND: typeof import("@redis/json/dist/commands/STRAPPEND");
+ strAppend: typeof import("@redis/json/dist/commands/STRAPPEND");
+ STRLEN: typeof import("@redis/json/dist/commands/STRLEN");
+ strLen: typeof import("@redis/json/dist/commands/STRLEN");
+ TYPE: typeof import("@redis/json/dist/commands/TYPE");
+ type: typeof import("@redis/json/dist/commands/TYPE");
+ };
+ ft: {
+ _LIST: typeof import("@redis/search/dist/commands/_LIST");
+ _list: typeof import("@redis/search/dist/commands/_LIST");
+ ALTER: typeof import("@redis/search/dist/commands/ALTER");
+ alter: typeof import("@redis/search/dist/commands/ALTER");
+ AGGREGATE_WITHCURSOR: typeof import("@redis/search/dist/commands/AGGREGATE_WITHCURSOR");
+ aggregateWithCursor: typeof import("@redis/search/dist/commands/AGGREGATE_WITHCURSOR");
+ AGGREGATE: typeof import("@redis/search/dist/commands/AGGREGATE");
+ aggregate: typeof import("@redis/search/dist/commands/AGGREGATE");
+ ALIASADD: typeof import("@redis/search/dist/commands/ALIASADD");
+ aliasAdd: typeof import("@redis/search/dist/commands/ALIASADD");
+ ALIASDEL: typeof import("@redis/search/dist/commands/ALIASDEL");
+ aliasDel: typeof import("@redis/search/dist/commands/ALIASDEL");
+ ALIASUPDATE: typeof import("@redis/search/dist/commands/ALIASUPDATE");
+ aliasUpdate: typeof import("@redis/search/dist/commands/ALIASUPDATE");
+ CONFIG_GET: typeof import("@redis/search/dist/commands/CONFIG_GET");
+ configGet: typeof import("@redis/search/dist/commands/CONFIG_GET");
+ CONFIG_SET: typeof import("@redis/search/dist/commands/CONFIG_SET");
+ configSet: typeof import("@redis/search/dist/commands/CONFIG_SET");
+ CREATE: typeof import("@redis/search/dist/commands/CREATE");
+ create: typeof import("@redis/search/dist/commands/CREATE");
+ CURSOR_DEL: typeof import("@redis/search/dist/commands/CURSOR_DEL");
+ cursorDel: typeof import("@redis/search/dist/commands/CURSOR_DEL");
+ CURSOR_READ: typeof import("@redis/search/dist/commands/CURSOR_READ");
+ cursorRead: typeof import("@redis/search/dist/commands/CURSOR_READ");
+ DICTADD: typeof import("@redis/search/dist/commands/DICTADD");
+ dictAdd: typeof import("@redis/search/dist/commands/DICTADD");
+ DICTDEL: typeof import("@redis/search/dist/commands/DICTDEL");
+ dictDel: typeof import("@redis/search/dist/commands/DICTDEL");
+ DICTDUMP: typeof import("@redis/search/dist/commands/DICTDUMP");
+ dictDump: typeof import("@redis/search/dist/commands/DICTDUMP");
+ DROPINDEX: typeof import("@redis/search/dist/commands/DROPINDEX");
+ dropIndex: typeof import("@redis/search/dist/commands/DROPINDEX");
+ EXPLAIN: typeof import("@redis/search/dist/commands/EXPLAIN");
+ explain: typeof import("@redis/search/dist/commands/EXPLAIN");
+ EXPLAINCLI: typeof import("@redis/search/dist/commands/EXPLAINCLI");
+ explainCli: typeof import("@redis/search/dist/commands/EXPLAINCLI");
+ INFO: typeof import("@redis/search/dist/commands/INFO");
+ info: typeof import("@redis/search/dist/commands/INFO");
+ PROFILESEARCH: typeof import("@redis/search/dist/commands/PROFILE_SEARCH");
+ profileSearch: typeof import("@redis/search/dist/commands/PROFILE_SEARCH");
+ PROFILEAGGREGATE: typeof import("@redis/search/dist/commands/PROFILE_AGGREGATE");
+ profileAggregate: typeof import("@redis/search/dist/commands/PROFILE_AGGREGATE");
+ SEARCH: typeof import("@redis/search/dist/commands/SEARCH");
+ search: typeof import("@redis/search/dist/commands/SEARCH");
+ SEARCH_NOCONTENT: typeof import("@redis/search/dist/commands/SEARCH_NOCONTENT");
+ searchNoContent: typeof import("@redis/search/dist/commands/SEARCH_NOCONTENT");
+ SPELLCHECK: typeof import("@redis/search/dist/commands/SPELLCHECK");
+ spellCheck: typeof import("@redis/search/dist/commands/SPELLCHECK");
+ SUGADD: typeof import("@redis/search/dist/commands/SUGADD");
+ sugAdd: typeof import("@redis/search/dist/commands/SUGADD");
+ SUGDEL: typeof import("@redis/search/dist/commands/SUGDEL");
+ sugDel: typeof import("@redis/search/dist/commands/SUGDEL");
+ SUGGET_WITHPAYLOADS: typeof import("@redis/search/dist/commands/SUGGET_WITHPAYLOADS");
+ sugGetWithPayloads: typeof import("@redis/search/dist/commands/SUGGET_WITHPAYLOADS");
+ SUGGET_WITHSCORES_WITHPAYLOADS: typeof import("@redis/search/dist/commands/SUGGET_WITHSCORES_WITHPAYLOADS");
+ sugGetWithScoresWithPayloads: typeof import("@redis/search/dist/commands/SUGGET_WITHSCORES_WITHPAYLOADS");
+ SUGGET_WITHSCORES: typeof import("@redis/search/dist/commands/SUGGET_WITHSCORES");
+ sugGetWithScores: typeof import("@redis/search/dist/commands/SUGGET_WITHSCORES");
+ SUGGET: typeof import("@redis/search/dist/commands/SUGGET");
+ sugGet: typeof import("@redis/search/dist/commands/SUGGET");
+ SUGLEN: typeof import("@redis/search/dist/commands/SUGLEN");
+ sugLen: typeof import("@redis/search/dist/commands/SUGLEN");
+ SYNDUMP: typeof import("@redis/search/dist/commands/SYNDUMP");
+ synDump: typeof import("@redis/search/dist/commands/SYNDUMP");
+ SYNUPDATE: typeof import("@redis/search/dist/commands/SYNUPDATE");
+ synUpdate: typeof import("@redis/search/dist/commands/SYNUPDATE");
+ TAGVALS: typeof import("@redis/search/dist/commands/TAGVALS");
+ tagVals: typeof import("@redis/search/dist/commands/TAGVALS");
+ };
+ ts: {
+ ADD: typeof import("@redis/time-series/dist/commands/ADD");
+ add: typeof import("@redis/time-series/dist/commands/ADD");
+ ALTER: typeof import("@redis/time-series/dist/commands/ALTER");
+ alter: typeof import("@redis/time-series/dist/commands/ALTER");
+ CREATE: typeof import("@redis/time-series/dist/commands/CREATE");
+ create: typeof import("@redis/time-series/dist/commands/CREATE");
+ CREATERULE: typeof import("@redis/time-series/dist/commands/CREATERULE");
+ createRule: typeof import("@redis/time-series/dist/commands/CREATERULE");
+ DECRBY: typeof import("@redis/time-series/dist/commands/DECRBY");
+ decrBy: typeof import("@redis/time-series/dist/commands/DECRBY");
+ DEL: typeof import("@redis/time-series/dist/commands/DEL");
+ del: typeof import("@redis/time-series/dist/commands/DEL");
+ DELETERULE: typeof import("@redis/time-series/dist/commands/DELETERULE");
+ deleteRule: typeof import("@redis/time-series/dist/commands/DELETERULE");
+ GET: typeof import("@redis/time-series/dist/commands/GET");
+ get: typeof import("@redis/time-series/dist/commands/GET");
+ INCRBY: typeof import("@redis/time-series/dist/commands/INCRBY");
+ incrBy: typeof import("@redis/time-series/dist/commands/INCRBY");
+ INFO_DEBUG: typeof import("@redis/time-series/dist/commands/INFO_DEBUG");
+ infoDebug: typeof import("@redis/time-series/dist/commands/INFO_DEBUG");
+ INFO: typeof import("@redis/time-series/dist/commands/INFO");
+ info: typeof import("@redis/time-series/dist/commands/INFO");
+ MADD: typeof import("@redis/time-series/dist/commands/MADD");
+ mAdd: typeof import("@redis/time-series/dist/commands/MADD");
+ MGET: typeof import("@redis/time-series/dist/commands/MGET");
+ mGet: typeof import("@redis/time-series/dist/commands/MGET");
+ MGET_WITHLABELS: typeof import("@redis/time-series/dist/commands/MGET_WITHLABELS");
+ mGetWithLabels: typeof import("@redis/time-series/dist/commands/MGET_WITHLABELS");
+ QUERYINDEX: typeof import("@redis/time-series/dist/commands/QUERYINDEX");
+ queryIndex: typeof import("@redis/time-series/dist/commands/QUERYINDEX");
+ RANGE: typeof import("@redis/time-series/dist/commands/RANGE");
+ range: typeof import("@redis/time-series/dist/commands/RANGE");
+ REVRANGE: typeof import("@redis/time-series/dist/commands/REVRANGE");
+ revRange: typeof import("@redis/time-series/dist/commands/REVRANGE");
+ MRANGE: typeof import("@redis/time-series/dist/commands/MRANGE");
+ mRange: typeof import("@redis/time-series/dist/commands/MRANGE");
+ MRANGE_WITHLABELS: typeof import("@redis/time-series/dist/commands/MRANGE_WITHLABELS");
+ mRangeWithLabels: typeof import("@redis/time-series/dist/commands/MRANGE_WITHLABELS");
+ MREVRANGE: typeof import("@redis/time-series/dist/commands/MREVRANGE");
+ mRevRange: typeof import("@redis/time-series/dist/commands/MREVRANGE");
+ MREVRANGE_WITHLABELS: typeof import("@redis/time-series/dist/commands/MREVRANGE_WITHLABELS");
+ mRevRangeWithLabels: typeof import("@redis/time-series/dist/commands/MREVRANGE_WITHLABELS");
+ };
+ bf: {
+ ADD: typeof import("@redis/bloom/dist/commands/bloom/ADD");
+ add: typeof import("@redis/bloom/dist/commands/bloom/ADD");
+ CARD: typeof import("@redis/bloom/dist/commands/bloom/CARD");
+ card: typeof import("@redis/bloom/dist/commands/bloom/CARD");
+ EXISTS: typeof import("@redis/bloom/dist/commands/bloom/EXISTS");
+ exists: typeof import("@redis/bloom/dist/commands/bloom/EXISTS");
+ INFO: typeof import("@redis/bloom/dist/commands/bloom/INFO");
+ info: typeof import("@redis/bloom/dist/commands/bloom/INFO");
+ INSERT: typeof import("@redis/bloom/dist/commands/bloom/INSERT");
+ insert: typeof import("@redis/bloom/dist/commands/bloom/INSERT");
+ LOADCHUNK: typeof import("@redis/bloom/dist/commands/bloom/LOADCHUNK");
+ loadChunk: typeof import("@redis/bloom/dist/commands/bloom/LOADCHUNK");
+ MADD: typeof import("@redis/bloom/dist/commands/bloom/MADD");
+ mAdd: typeof import("@redis/bloom/dist/commands/bloom/MADD");
+ MEXISTS: typeof import("@redis/bloom/dist/commands/bloom/MEXISTS");
+ mExists: typeof import("@redis/bloom/dist/commands/bloom/MEXISTS");
+ RESERVE: typeof import("@redis/bloom/dist/commands/bloom/RESERVE");
+ reserve: typeof import("@redis/bloom/dist/commands/bloom/RESERVE");
+ SCANDUMP: typeof import("@redis/bloom/dist/commands/bloom/SCANDUMP");
+ scanDump: typeof import("@redis/bloom/dist/commands/bloom/SCANDUMP");
+ };
+ cms: {
+ INCRBY: typeof import("@redis/bloom/dist/commands/count-min-sketch/INCRBY");
+ incrBy: typeof import("@redis/bloom/dist/commands/count-min-sketch/INCRBY");
+ INFO: typeof import("@redis/bloom/dist/commands/count-min-sketch/INFO");
+ info: typeof import("@redis/bloom/dist/commands/count-min-sketch/INFO");
+ INITBYDIM: typeof import("@redis/bloom/dist/commands/count-min-sketch/INITBYDIM");
+ initByDim: typeof import("@redis/bloom/dist/commands/count-min-sketch/INITBYDIM");
+ INITBYPROB: typeof import("@redis/bloom/dist/commands/count-min-sketch/INITBYPROB");
+ initByProb: typeof import("@redis/bloom/dist/commands/count-min-sketch/INITBYPROB");
+ MERGE: typeof import("@redis/bloom/dist/commands/count-min-sketch/MERGE");
+ merge: typeof import("@redis/bloom/dist/commands/count-min-sketch/MERGE");
+ QUERY: typeof import("@redis/bloom/dist/commands/count-min-sketch/QUERY");
+ query: typeof import("@redis/bloom/dist/commands/count-min-sketch/QUERY");
+ };
+ cf: {
+ ADD: typeof import("@redis/bloom/dist/commands/cuckoo/ADD");
+ add: typeof import("@redis/bloom/dist/commands/cuckoo/ADD");
+ ADDNX: typeof import("@redis/bloom/dist/commands/cuckoo/ADDNX");
+ addNX: typeof import("@redis/bloom/dist/commands/cuckoo/ADDNX");
+ COUNT: typeof import("@redis/bloom/dist/commands/cuckoo/COUNT");
+ count: typeof import("@redis/bloom/dist/commands/cuckoo/COUNT");
+ DEL: typeof import("@redis/bloom/dist/commands/cuckoo/DEL");
+ del: typeof import("@redis/bloom/dist/commands/cuckoo/DEL");
+ EXISTS: typeof import("@redis/bloom/dist/commands/cuckoo/EXISTS");
+ exists: typeof import("@redis/bloom/dist/commands/cuckoo/EXISTS");
+ INFO: typeof import("@redis/bloom/dist/commands/cuckoo/INFO");
+ info: typeof import("@redis/bloom/dist/commands/cuckoo/INFO");
+ INSERT: typeof import("@redis/bloom/dist/commands/cuckoo/INSERT");
+ insert: typeof import("@redis/bloom/dist/commands/cuckoo/INSERT");
+ INSERTNX: typeof import("@redis/bloom/dist/commands/cuckoo/INSERTNX");
+ insertNX: typeof import("@redis/bloom/dist/commands/cuckoo/INSERTNX");
+ LOADCHUNK: typeof import("@redis/bloom/dist/commands/cuckoo/LOADCHUNK");
+ loadChunk: typeof import("@redis/bloom/dist/commands/cuckoo/LOADCHUNK");
+ RESERVE: typeof import("@redis/bloom/dist/commands/cuckoo/RESERVE");
+ reserve: typeof import("@redis/bloom/dist/commands/cuckoo/RESERVE");
+ SCANDUMP: typeof import("@redis/bloom/dist/commands/cuckoo/SCANDUMP");
+ scanDump: typeof import("@redis/bloom/dist/commands/cuckoo/SCANDUMP");
+ };
+ tDigest: {
+ ADD: typeof import("@redis/bloom/dist/commands/t-digest/ADD");
+ add: typeof import("@redis/bloom/dist/commands/t-digest/ADD");
+ BYRANK: typeof import("@redis/bloom/dist/commands/t-digest/BYRANK");
+ byRank: typeof import("@redis/bloom/dist/commands/t-digest/BYRANK");
+ BYREVRANK: typeof import("@redis/bloom/dist/commands/t-digest/BYREVRANK");
+ byRevRank: typeof import("@redis/bloom/dist/commands/t-digest/BYREVRANK");
+ CDF: typeof import("@redis/bloom/dist/commands/t-digest/CDF");
+ cdf: typeof import("@redis/bloom/dist/commands/t-digest/CDF");
+ CREATE: typeof import("@redis/bloom/dist/commands/t-digest/CREATE");
+ create: typeof import("@redis/bloom/dist/commands/t-digest/CREATE");
+ INFO: typeof import("@redis/bloom/dist/commands/t-digest/INFO");
+ info: typeof import("@redis/bloom/dist/commands/t-digest/INFO");
+ MAX: typeof import("@redis/bloom/dist/commands/t-digest/MAX");
+ max: typeof import("@redis/bloom/dist/commands/t-digest/MAX");
+ MERGE: typeof import("@redis/bloom/dist/commands/t-digest/MERGE");
+ merge: typeof import("@redis/bloom/dist/commands/t-digest/MERGE");
+ MIN: typeof import("@redis/bloom/dist/commands/t-digest/MIN");
+ min: typeof import("@redis/bloom/dist/commands/t-digest/MIN");
+ QUANTILE: typeof import("@redis/bloom/dist/commands/t-digest/QUANTILE");
+ quantile: typeof import("@redis/bloom/dist/commands/t-digest/QUANTILE");
+ RANK: typeof import("@redis/bloom/dist/commands/t-digest/RANK");
+ rank: typeof import("@redis/bloom/dist/commands/t-digest/RANK");
+ RESET: typeof import("@redis/bloom/dist/commands/t-digest/RESET");
+ reset: typeof import("@redis/bloom/dist/commands/t-digest/RESET");
+ REVRANK: typeof import("@redis/bloom/dist/commands/t-digest/REVRANK");
+ revRank: typeof import("@redis/bloom/dist/commands/t-digest/REVRANK");
+ TRIMMED_MEAN: typeof import("@redis/bloom/dist/commands/t-digest/TRIMMED_MEAN");
+ trimmedMean: typeof import("@redis/bloom/dist/commands/t-digest/TRIMMED_MEAN");
+ };
+ topK: {
+ ADD: typeof import("@redis/bloom/dist/commands/top-k/ADD");
+ add: typeof import("@redis/bloom/dist/commands/top-k/ADD");
+ COUNT: typeof import("@redis/bloom/dist/commands/top-k/COUNT");
+ count: typeof import("@redis/bloom/dist/commands/top-k/COUNT");
+ INCRBY: typeof import("@redis/bloom/dist/commands/top-k/INCRBY");
+ incrBy: typeof import("@redis/bloom/dist/commands/top-k/INCRBY");
+ INFO: typeof import("@redis/bloom/dist/commands/top-k/INFO");
+ info: typeof import("@redis/bloom/dist/commands/top-k/INFO");
+ LIST_WITHCOUNT: typeof import("@redis/bloom/dist/commands/top-k/LIST_WITHCOUNT");
+ listWithCount: typeof import("@redis/bloom/dist/commands/top-k/LIST_WITHCOUNT");
+ LIST: typeof import("@redis/bloom/dist/commands/top-k/LIST");
+ list: typeof import("@redis/bloom/dist/commands/top-k/LIST");
+ QUERY: typeof import("@redis/bloom/dist/commands/top-k/QUERY");
+ query: typeof import("@redis/bloom/dist/commands/top-k/QUERY");
+ RESERVE: typeof import("@redis/bloom/dist/commands/top-k/RESERVE");
+ reserve: typeof import("@redis/bloom/dist/commands/top-k/RESERVE");
+ };
+} & import("redis").RedisModules, import("redis").RedisFunctions, import("redis").RedisScripts>;
+export default redisClient;
+//# sourceMappingURL=redis.d.ts.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/config/redis.d.ts.map b/backend-old-20260125/dist/config/redis.d.ts.map
new file mode 100644
index 0000000..dd5a90d
--- /dev/null
+++ b/backend-old-20260125/dist/config/redis.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"redis.d.ts","sourceRoot":"","sources":["../../src/config/redis.ts"],"names":[],"mappings":"AAKA,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+FAEf,CAAC;AAeH,eAAe,WAAW,CAAC"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/config/redis.js b/backend-old-20260125/dist/config/redis.js
new file mode 100644
index 0000000..fe1c567
--- /dev/null
+++ b/backend-old-20260125/dist/config/redis.js
@@ -0,0 +1,23 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const redis_1 = require("redis");
+const dotenv_1 = __importDefault(require("dotenv"));
+dotenv_1.default.config();
+const redisClient = (0, redis_1.createClient)({
+ url: process.env.REDIS_URL || 'redis://localhost:6379'
+});
+redisClient.on('connect', () => {
+ console.log('✅ Connected to Redis');
+});
+redisClient.on('error', (err) => {
+ console.error('❌ Redis connection error:', err);
+});
+// Connect to Redis
+redisClient.connect().catch((err) => {
+ console.error('❌ Failed to connect to Redis:', err);
+});
+exports.default = redisClient;
+//# sourceMappingURL=redis.js.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/config/redis.js.map b/backend-old-20260125/dist/config/redis.js.map
new file mode 100644
index 0000000..09cff73
--- /dev/null
+++ b/backend-old-20260125/dist/config/redis.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"redis.js","sourceRoot":"","sources":["../../src/config/redis.ts"],"names":[],"mappings":";;;;;AAAA,iCAAqC;AACrC,oDAA4B;AAE5B,gBAAM,CAAC,MAAM,EAAE,CAAC;AAEhB,MAAM,WAAW,GAAG,IAAA,oBAAY,EAAC;IAC/B,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,wBAAwB;CACvD,CAAC,CAAC;AAEH,WAAW,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;IAC7B,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;AACtC,CAAC,CAAC,CAAC;AAEH,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAU,EAAE,EAAE;IACrC,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,GAAG,CAAC,CAAC;AAClD,CAAC,CAAC,CAAC;AAEH,mBAAmB;AACnB,WAAW,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,GAAU,EAAE,EAAE;IACzC,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,GAAG,CAAC,CAAC;AACtD,CAAC,CAAC,CAAC;AAEH,kBAAe,WAAW,CAAC"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/config/simpleAuth.d.ts b/backend-old-20260125/dist/config/simpleAuth.d.ts
new file mode 100644
index 0000000..b033f7a
--- /dev/null
+++ b/backend-old-20260125/dist/config/simpleAuth.d.ts
@@ -0,0 +1,9 @@
+import { User } from '../services/jwtKeyManager';
+export { User } from '../services/jwtKeyManager';
+export declare function generateToken(user: User): string;
+export declare function verifyToken(token: string): User | null;
+export declare function verifyGoogleToken(googleToken: string): Promise;
+export declare function getGoogleAuthUrl(): string;
+export declare function exchangeCodeForTokens(code: string): Promise;
+export declare function getGoogleUserInfo(accessToken: string): Promise;
+//# sourceMappingURL=simpleAuth.d.ts.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/config/simpleAuth.d.ts.map b/backend-old-20260125/dist/config/simpleAuth.d.ts.map
new file mode 100644
index 0000000..8b4ef7d
--- /dev/null
+++ b/backend-old-20260125/dist/config/simpleAuth.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"simpleAuth.d.ts","sourceRoot":"","sources":["../../src/config/simpleAuth.ts"],"names":[],"mappings":"AAAA,OAAsB,EAAE,IAAI,EAAE,MAAM,2BAA2B,CAAC;AAKhE,OAAO,EAAE,IAAI,EAAE,MAAM,2BAA2B,CAAC;AAEjD,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAEhD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAEtD;AAGD,wBAAsB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAWzE;AAGD,wBAAgB,gBAAgB,IAAI,MAAM,CAiCzC;AAGD,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAgGtE;AAGD,wBAAsB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAsEzE"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/config/simpleAuth.js b/backend-old-20260125/dist/config/simpleAuth.js
new file mode 100644
index 0000000..8b4b522
--- /dev/null
+++ b/backend-old-20260125/dist/config/simpleAuth.js
@@ -0,0 +1,217 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.User = void 0;
+exports.generateToken = generateToken;
+exports.verifyToken = verifyToken;
+exports.verifyGoogleToken = verifyGoogleToken;
+exports.getGoogleAuthUrl = getGoogleAuthUrl;
+exports.exchangeCodeForTokens = exchangeCodeForTokens;
+exports.getGoogleUserInfo = getGoogleUserInfo;
+const jwtKeyManager_1 = __importDefault(require("../services/jwtKeyManager"));
+// JWT Key Manager now handles all token operations with automatic rotation
+// No more static JWT_SECRET needed!
+var jwtKeyManager_2 = require("../services/jwtKeyManager");
+Object.defineProperty(exports, "User", { enumerable: true, get: function () { return jwtKeyManager_2.User; } });
+function generateToken(user) {
+ return jwtKeyManager_1.default.generateToken(user);
+}
+function verifyToken(token) {
+ return jwtKeyManager_1.default.verifyToken(token);
+}
+// Simple Google OAuth2 client using fetch
+async function verifyGoogleToken(googleToken) {
+ try {
+ const response = await fetch(`https://www.googleapis.com/oauth2/v1/userinfo?access_token=${googleToken}`);
+ if (!response.ok) {
+ throw new Error('Invalid Google token');
+ }
+ return await response.json();
+ }
+ catch (error) {
+ console.error('Error verifying Google token:', error);
+ return null;
+ }
+}
+// Get Google OAuth2 URL
+function getGoogleAuthUrl() {
+ const clientId = process.env.GOOGLE_CLIENT_ID;
+ const redirectUri = process.env.GOOGLE_REDIRECT_URI || 'http://localhost:3000/auth/google/callback';
+ console.log('🔗 Generating Google OAuth URL:', {
+ client_id_present: !!clientId,
+ redirect_uri: redirectUri,
+ environment: process.env.NODE_ENV || 'development'
+ });
+ if (!clientId) {
+ console.error('❌ GOOGLE_CLIENT_ID not configured');
+ throw new Error('GOOGLE_CLIENT_ID not configured');
+ }
+ if (!redirectUri.startsWith('http')) {
+ console.error('❌ Invalid redirect URI:', redirectUri);
+ throw new Error('GOOGLE_REDIRECT_URI must be a valid HTTP/HTTPS URL');
+ }
+ const params = new URLSearchParams({
+ client_id: clientId,
+ redirect_uri: redirectUri,
+ response_type: 'code',
+ scope: 'openid email profile',
+ access_type: 'offline',
+ prompt: 'consent'
+ });
+ const authUrl = `https://accounts.google.com/o/oauth2/v2/auth?${params.toString()}`;
+ console.log('✅ Google OAuth URL generated successfully');
+ return authUrl;
+}
+// Exchange authorization code for tokens
+async function exchangeCodeForTokens(code) {
+ const clientId = process.env.GOOGLE_CLIENT_ID;
+ const clientSecret = process.env.GOOGLE_CLIENT_SECRET;
+ const redirectUri = process.env.GOOGLE_REDIRECT_URI || 'http://localhost:3000/auth/google/callback';
+ console.log('🔄 Exchanging OAuth code for tokens:', {
+ client_id_present: !!clientId,
+ client_secret_present: !!clientSecret,
+ redirect_uri: redirectUri,
+ code_length: code?.length || 0
+ });
+ if (!clientId || !clientSecret) {
+ console.error('❌ Google OAuth credentials not configured:', {
+ client_id: !!clientId,
+ client_secret: !!clientSecret
+ });
+ throw new Error('Google OAuth credentials not configured');
+ }
+ if (!code || code.length < 10) {
+ console.error('❌ Invalid authorization code:', { code_length: code?.length || 0 });
+ throw new Error('Invalid authorization code provided');
+ }
+ try {
+ const tokenUrl = 'https://oauth2.googleapis.com/token';
+ const requestBody = new URLSearchParams({
+ client_id: clientId,
+ client_secret: clientSecret,
+ code,
+ grant_type: 'authorization_code',
+ redirect_uri: redirectUri,
+ });
+ console.log('📡 Making token exchange request to Google:', {
+ url: tokenUrl,
+ redirect_uri: redirectUri,
+ grant_type: 'authorization_code'
+ });
+ const response = await fetch(tokenUrl, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ 'Accept': 'application/json'
+ },
+ body: requestBody,
+ });
+ const responseText = await response.text();
+ console.log('📨 Token exchange response:', {
+ status: response.status,
+ ok: response.ok,
+ content_type: response.headers.get('content-type'),
+ response_length: responseText.length
+ });
+ if (!response.ok) {
+ console.error('❌ Token exchange failed:', {
+ status: response.status,
+ statusText: response.statusText,
+ response: responseText
+ });
+ throw new Error(`Failed to exchange code for tokens: ${response.status} ${response.statusText}`);
+ }
+ let tokenData;
+ try {
+ tokenData = JSON.parse(responseText);
+ }
+ catch (parseError) {
+ console.error('❌ Failed to parse token response:', { response: responseText });
+ throw new Error('Invalid JSON response from Google token endpoint');
+ }
+ if (!tokenData.access_token) {
+ console.error('❌ No access token in response:', tokenData);
+ throw new Error('No access token received from Google');
+ }
+ console.log('✅ Token exchange successful:', {
+ has_access_token: !!tokenData.access_token,
+ has_refresh_token: !!tokenData.refresh_token,
+ token_type: tokenData.token_type,
+ expires_in: tokenData.expires_in
+ });
+ return tokenData;
+ }
+ catch (error) {
+ console.error('❌ Error exchanging code for tokens:', {
+ error: error instanceof Error ? error.message : 'Unknown error',
+ stack: error instanceof Error ? error.stack : undefined
+ });
+ throw error;
+ }
+}
+// Get user info from Google
+async function getGoogleUserInfo(accessToken) {
+ console.log('👤 Getting user info from Google:', {
+ token_length: accessToken?.length || 0,
+ token_prefix: accessToken ? accessToken.substring(0, 10) + '...' : 'none'
+ });
+ if (!accessToken || accessToken.length < 10) {
+ console.error('❌ Invalid access token for user info request');
+ throw new Error('Invalid access token provided');
+ }
+ try {
+ const userInfoUrl = `https://www.googleapis.com/oauth2/v2/userinfo?access_token=${accessToken}`;
+ console.log('📡 Making user info request to Google');
+ const response = await fetch(userInfoUrl, {
+ method: 'GET',
+ headers: {
+ 'Accept': 'application/json',
+ 'Authorization': `Bearer ${accessToken}`
+ }
+ });
+ const responseText = await response.text();
+ console.log('📨 User info response:', {
+ status: response.status,
+ ok: response.ok,
+ content_type: response.headers.get('content-type'),
+ response_length: responseText.length
+ });
+ if (!response.ok) {
+ console.error('❌ Failed to get user info:', {
+ status: response.status,
+ statusText: response.statusText,
+ response: responseText
+ });
+ throw new Error(`Failed to get user info: ${response.status} ${response.statusText}`);
+ }
+ let userData;
+ try {
+ userData = JSON.parse(responseText);
+ }
+ catch (parseError) {
+ console.error('❌ Failed to parse user info response:', { response: responseText });
+ throw new Error('Invalid JSON response from Google user info endpoint');
+ }
+ if (!userData.email) {
+ console.error('❌ No email in user info response:', userData);
+ throw new Error('No email address received from Google');
+ }
+ console.log('✅ User info retrieved successfully:', {
+ email: userData.email,
+ name: userData.name,
+ verified_email: userData.verified_email,
+ has_picture: !!userData.picture
+ });
+ return userData;
+ }
+ catch (error) {
+ console.error('❌ Error getting Google user info:', {
+ error: error instanceof Error ? error.message : 'Unknown error',
+ stack: error instanceof Error ? error.stack : undefined
+ });
+ throw error;
+ }
+}
+//# sourceMappingURL=simpleAuth.js.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/config/simpleAuth.js.map b/backend-old-20260125/dist/config/simpleAuth.js.map
new file mode 100644
index 0000000..c445f39
--- /dev/null
+++ b/backend-old-20260125/dist/config/simpleAuth.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"simpleAuth.js","sourceRoot":"","sources":["../../src/config/simpleAuth.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/index.d.ts b/backend-old-20260125/dist/index.d.ts
new file mode 100644
index 0000000..e26a57a
--- /dev/null
+++ b/backend-old-20260125/dist/index.d.ts
@@ -0,0 +1,2 @@
+export {};
+//# sourceMappingURL=index.d.ts.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/index.d.ts.map b/backend-old-20260125/dist/index.d.ts.map
new file mode 100644
index 0000000..535b86d
--- /dev/null
+++ b/backend-old-20260125/dist/index.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/index.js b/backend-old-20260125/dist/index.js
new file mode 100644
index 0000000..9106662
--- /dev/null
+++ b/backend-old-20260125/dist/index.js
@@ -0,0 +1,271 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const express_1 = __importDefault(require("express"));
+const cors_1 = __importDefault(require("cors"));
+const dotenv_1 = __importDefault(require("dotenv"));
+const authService_1 = __importDefault(require("./services/authService"));
+const unifiedDataService_1 = __importDefault(require("./services/unifiedDataService"));
+const simpleValidation_1 = require("./middleware/simpleValidation");
+const errorHandler_1 = require("./middleware/errorHandler");
+dotenv_1.default.config();
+// Log environment variables status on startup
+console.log('Environment variables loaded:');
+console.log('- GOOGLE_CLIENT_ID:', process.env.GOOGLE_CLIENT_ID ? 'Set' : 'Not set');
+console.log('- GOOGLE_CLIENT_SECRET:', process.env.GOOGLE_CLIENT_SECRET ? 'Set' : 'Not set');
+console.log('- GOOGLE_REDIRECT_URI:', process.env.GOOGLE_REDIRECT_URI || 'Not set');
+const app = (0, express_1.default)();
+const port = process.env.PORT || 3000;
+// Middleware
+app.use((0, cors_1.default)({
+ origin: [
+ process.env.FRONTEND_URL || 'http://localhost:5173',
+ 'https://bsa.madeamess.online'
+ ],
+ credentials: true
+}));
+app.use(express_1.default.json());
+app.use(express_1.default.static('public'));
+// Health check
+app.get('/api/health', (req, res) => {
+ res.json({
+ status: 'OK',
+ timestamp: new Date().toISOString(),
+ version: '2.0.0' // Simplified version
+ });
+});
+// Auth routes
+app.get('/auth/setup', async (req, res) => {
+ try {
+ // Check if any users exist in the system
+ const userCount = await unifiedDataService_1.default.getUserCount();
+ res.json({
+ needsSetup: userCount === 0,
+ hasUsers: userCount > 0
+ });
+ }
+ catch (error) {
+ console.error('Error in /auth/setup:', error);
+ res.status(500).json({ error: 'Failed to check setup status' });
+ }
+});
+app.get('/auth/google', (req, res) => {
+ res.redirect(authService_1.default.getGoogleAuthUrl());
+});
+app.get('/auth/google/url', (req, res) => {
+ try {
+ // Return the Google OAuth URL as JSON for the frontend
+ const url = authService_1.default.getGoogleAuthUrl();
+ res.json({ url });
+ }
+ catch (error) {
+ console.error('Error generating Google Auth URL:', error);
+ res.status(500).json({
+ error: 'Google OAuth configuration error',
+ message: error.message
+ });
+ }
+});
+app.post('/auth/google/callback', async (req, res) => {
+ try {
+ const { code } = req.body;
+ const { user, token } = await authService_1.default.handleGoogleAuth(code);
+ res.json({ user, token });
+ }
+ catch (error) {
+ res.status(400).json({ error: 'Authentication failed' });
+ }
+});
+app.post('/auth/google/exchange', async (req, res) => {
+ try {
+ const { code } = req.body;
+ const { user, token } = await authService_1.default.handleGoogleAuth(code);
+ res.json({ user, token });
+ }
+ catch (error) {
+ res.status(400).json({ error: 'Authentication failed' });
+ }
+});
+app.post('/auth/google/verify', async (req, res) => {
+ try {
+ const { credential } = req.body;
+ const { user, token } = await authService_1.default.verifyGoogleToken(credential);
+ res.json({ user, token });
+ }
+ catch (error) {
+ console.error('Google token verification error:', error);
+ res.status(400).json({ error: 'Authentication failed' });
+ }
+});
+app.get('/auth/me', authService_1.default.requireAuth, (req, res) => {
+ res.json(req.user);
+});
+app.post('/auth/logout', (req, res) => {
+ res.json({ message: 'Logged out successfully' });
+});
+// VIP routes
+app.get('/api/vips', async (req, res, next) => {
+ try {
+ const vips = await unifiedDataService_1.default.getVips();
+ res.json(vips);
+ }
+ catch (error) {
+ next(error);
+ }
+});
+app.get('/api/vips/:id', async (req, res, next) => {
+ try {
+ const vip = await unifiedDataService_1.default.getVipById(req.params.id);
+ if (!vip)
+ return res.status(404).json({ error: 'VIP not found' });
+ res.json(vip);
+ }
+ catch (error) {
+ next(error);
+ }
+});
+app.post('/api/vips', authService_1.default.requireAuth, authService_1.default.requireRole(['coordinator', 'administrator']), (0, simpleValidation_1.validate)(simpleValidation_1.schemas.createVip), async (req, res, next) => {
+ try {
+ const vip = await unifiedDataService_1.default.createVip(req.body);
+ res.status(201).json(vip);
+ }
+ catch (error) {
+ next(error);
+ }
+});
+app.put('/api/vips/:id', authService_1.default.requireAuth, authService_1.default.requireRole(['coordinator', 'administrator']), (0, simpleValidation_1.validate)(simpleValidation_1.schemas.updateVip), async (req, res, next) => {
+ try {
+ const vip = await unifiedDataService_1.default.updateVip(req.params.id, req.body);
+ if (!vip)
+ return res.status(404).json({ error: 'VIP not found' });
+ res.json(vip);
+ }
+ catch (error) {
+ next(error);
+ }
+});
+app.delete('/api/vips/:id', authService_1.default.requireAuth, authService_1.default.requireRole(['coordinator', 'administrator']), async (req, res, next) => {
+ try {
+ const vip = await unifiedDataService_1.default.deleteVip(req.params.id);
+ if (!vip)
+ return res.status(404).json({ error: 'VIP not found' });
+ res.json({ message: 'VIP deleted successfully' });
+ }
+ catch (error) {
+ next(error);
+ }
+});
+// Driver routes
+app.get('/api/drivers', async (req, res, next) => {
+ try {
+ const drivers = await unifiedDataService_1.default.getDrivers();
+ res.json(drivers);
+ }
+ catch (error) {
+ next(error);
+ }
+});
+app.post('/api/drivers', authService_1.default.requireAuth, authService_1.default.requireRole(['coordinator', 'administrator']), (0, simpleValidation_1.validate)(simpleValidation_1.schemas.createDriver), async (req, res, next) => {
+ try {
+ const driver = await unifiedDataService_1.default.createDriver(req.body);
+ res.status(201).json(driver);
+ }
+ catch (error) {
+ next(error);
+ }
+});
+app.put('/api/drivers/:id', authService_1.default.requireAuth, authService_1.default.requireRole(['coordinator', 'administrator']), (0, simpleValidation_1.validate)(simpleValidation_1.schemas.updateDriver), async (req, res, next) => {
+ try {
+ const driver = await unifiedDataService_1.default.updateDriver(req.params.id, req.body);
+ if (!driver)
+ return res.status(404).json({ error: 'Driver not found' });
+ res.json(driver);
+ }
+ catch (error) {
+ next(error);
+ }
+});
+app.delete('/api/drivers/:id', authService_1.default.requireAuth, authService_1.default.requireRole(['coordinator', 'administrator']), async (req, res, next) => {
+ try {
+ const driver = await unifiedDataService_1.default.deleteDriver(req.params.id);
+ if (!driver)
+ return res.status(404).json({ error: 'Driver not found' });
+ res.json({ message: 'Driver deleted successfully' });
+ }
+ catch (error) {
+ next(error);
+ }
+});
+// Schedule routes
+app.get('/api/vips/:vipId/schedule', authService_1.default.requireAuth, async (req, res, next) => {
+ try {
+ const schedule = await unifiedDataService_1.default.getScheduleByVipId(req.params.vipId);
+ res.json(schedule);
+ }
+ catch (error) {
+ next(error);
+ }
+});
+app.post('/api/vips/:vipId/schedule', authService_1.default.requireAuth, authService_1.default.requireRole(['coordinator', 'administrator']), (0, simpleValidation_1.validate)(simpleValidation_1.schemas.createScheduleEvent), async (req, res, next) => {
+ try {
+ const event = await unifiedDataService_1.default.createScheduleEvent(req.params.vipId, req.body);
+ res.status(201).json(event);
+ }
+ catch (error) {
+ next(error);
+ }
+});
+app.put('/api/vips/:vipId/schedule/:eventId', authService_1.default.requireAuth, authService_1.default.requireRole(['coordinator', 'administrator']), (0, simpleValidation_1.validate)(simpleValidation_1.schemas.updateScheduleEvent), async (req, res, next) => {
+ try {
+ const event = await unifiedDataService_1.default.updateScheduleEvent(req.params.eventId, req.body);
+ if (!event)
+ return res.status(404).json({ error: 'Event not found' });
+ res.json(event);
+ }
+ catch (error) {
+ next(error);
+ }
+});
+app.delete('/api/vips/:vipId/schedule/:eventId', authService_1.default.requireAuth, authService_1.default.requireRole(['coordinator', 'administrator']), async (req, res, next) => {
+ try {
+ const event = await unifiedDataService_1.default.deleteScheduleEvent(req.params.eventId);
+ if (!event)
+ return res.status(404).json({ error: 'Event not found' });
+ res.json({ message: 'Event deleted successfully' });
+ }
+ catch (error) {
+ next(error);
+ }
+});
+// Admin routes (simplified)
+app.get('/api/admin/settings', authService_1.default.requireAuth, authService_1.default.requireRole(['administrator']), async (req, res, next) => {
+ try {
+ const settings = await unifiedDataService_1.default.getAdminSettings();
+ res.json(settings);
+ }
+ catch (error) {
+ next(error);
+ }
+});
+app.post('/api/admin/settings', authService_1.default.requireAuth, authService_1.default.requireRole(['administrator']), async (req, res, next) => {
+ try {
+ const { key, value } = req.body;
+ await unifiedDataService_1.default.updateAdminSetting(key, value);
+ res.json({ message: 'Setting updated successfully' });
+ }
+ catch (error) {
+ next(error);
+ }
+});
+// Error handling
+app.use(errorHandler_1.notFoundHandler);
+app.use(errorHandler_1.errorHandler);
+// Start server
+app.listen(port, () => {
+ console.log(`🚀 Server running on port ${port}`);
+ console.log(`🏥 Health check: http://localhost:${port}/api/health`);
+ console.log(`📚 API docs: http://localhost:${port}/api-docs.html`);
+});
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/index.js.map b/backend-old-20260125/dist/index.js.map
new file mode 100644
index 0000000..66e6101
--- /dev/null
+++ b/backend-old-20260125/dist/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/index.original.d.ts b/backend-old-20260125/dist/index.original.d.ts
new file mode 100644
index 0000000..b090983
--- /dev/null
+++ b/backend-old-20260125/dist/index.original.d.ts
@@ -0,0 +1,2 @@
+export {};
+//# sourceMappingURL=index.original.d.ts.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/index.original.d.ts.map b/backend-old-20260125/dist/index.original.d.ts.map
new file mode 100644
index 0000000..ed1815b
--- /dev/null
+++ b/backend-old-20260125/dist/index.original.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.original.d.ts","sourceRoot":"","sources":["../src/index.original.ts"],"names":[],"mappings":""}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/index.original.js b/backend-old-20260125/dist/index.original.js
new file mode 100644
index 0000000..570abc3
--- /dev/null
+++ b/backend-old-20260125/dist/index.original.js
@@ -0,0 +1,765 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ var desc = Object.getOwnPropertyDescriptor(m, k);
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+ desc = { enumerable: true, get: function() { return m[k]; } };
+ }
+ Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ o[k2] = m[k];
+}));
+var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
+}) : function(o, v) {
+ o["default"] = v;
+});
+var __importStar = (this && this.__importStar) || (function () {
+ var ownKeys = function(o) {
+ ownKeys = Object.getOwnPropertyNames || function (o) {
+ var ar = [];
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
+ return ar;
+ };
+ return ownKeys(o);
+ };
+ return function (mod) {
+ if (mod && mod.__esModule) return mod;
+ var result = {};
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
+ __setModuleDefault(result, mod);
+ return result;
+ };
+})();
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const express_1 = __importDefault(require("express"));
+const dotenv_1 = __importDefault(require("dotenv"));
+const cors_1 = __importDefault(require("cors"));
+const simpleAuth_1 = __importStar(require("./routes/simpleAuth"));
+const flightService_1 = __importDefault(require("./services/flightService"));
+const driverConflictService_1 = __importDefault(require("./services/driverConflictService"));
+const scheduleValidationService_1 = __importDefault(require("./services/scheduleValidationService"));
+const flightTrackingScheduler_1 = __importDefault(require("./services/flightTrackingScheduler"));
+const enhancedDataService_1 = __importDefault(require("./services/enhancedDataService"));
+const databaseService_1 = __importDefault(require("./services/databaseService"));
+const jwtKeyManager_1 = __importDefault(require("./services/jwtKeyManager")); // Initialize JWT Key Manager
+const errorHandler_1 = require("./middleware/errorHandler");
+const logger_1 = require("./middleware/logger");
+const validation_1 = require("./middleware/validation");
+const schemas_1 = require("./types/schemas");
+dotenv_1.default.config();
+const app = (0, express_1.default)();
+const port = process.env.PORT ? parseInt(process.env.PORT) : 3000;
+// Middleware
+app.use((0, cors_1.default)({
+ origin: [
+ process.env.FRONTEND_URL || 'http://localhost:5173',
+ 'http://localhost:5173',
+ 'http://localhost:3000',
+ 'http://localhost', // Frontend Docker container (local testing)
+ 'https://bsa.madeamess.online' // Production frontend domain (where users access the site)
+ ],
+ credentials: true
+}));
+app.use(express_1.default.json());
+app.use(express_1.default.urlencoded({ extended: true }));
+// Add request logging
+app.use(logger_1.requestLogger);
+// Simple JWT-based authentication - no passport needed
+// Authentication routes
+app.use('/auth', simpleAuth_1.default);
+// Temporary admin bypass route (remove after setup)
+app.get('/admin-bypass', (req, res) => {
+ res.redirect(`${process.env.FRONTEND_URL || 'http://localhost:5173'}/admin?bypass=true`);
+});
+// Serve static files from public directory
+app.use(express_1.default.static('public'));
+// Enhanced health check endpoint with authentication system status
+app.get('/api/health', (0, errorHandler_1.asyncHandler)(async (req, res) => {
+ const timestamp = new Date().toISOString();
+ // Check JWT Key Manager status
+ const jwtStatus = jwtKeyManager_1.default.getStatus();
+ // Check environment variables
+ const envCheck = {
+ google_client_id: !!process.env.GOOGLE_CLIENT_ID,
+ google_client_secret: !!process.env.GOOGLE_CLIENT_SECRET,
+ google_redirect_uri: !!process.env.GOOGLE_REDIRECT_URI,
+ frontend_url: !!process.env.FRONTEND_URL,
+ database_url: !!process.env.DATABASE_URL,
+ admin_password: !!process.env.ADMIN_PASSWORD
+ };
+ // Check database connectivity
+ let databaseStatus = 'unknown';
+ let userCount = 0;
+ try {
+ userCount = await databaseService_1.default.getUserCount();
+ databaseStatus = 'connected';
+ }
+ catch (dbError) {
+ databaseStatus = 'disconnected';
+ console.error('Health check - Database error:', dbError);
+ }
+ // Overall system health
+ const isHealthy = databaseStatus === 'connected' &&
+ jwtStatus.hasCurrentKey &&
+ envCheck.google_client_id &&
+ envCheck.google_client_secret;
+ const healthData = {
+ status: isHealthy ? 'OK' : 'DEGRADED',
+ timestamp,
+ version: '1.0.0',
+ environment: process.env.NODE_ENV || 'development',
+ services: {
+ database: {
+ status: databaseStatus,
+ user_count: databaseStatus === 'connected' ? userCount : null
+ },
+ authentication: {
+ jwt_key_manager: jwtStatus,
+ oauth_configured: envCheck.google_client_id && envCheck.google_client_secret,
+ environment_variables: envCheck
+ }
+ },
+ uptime: process.uptime(),
+ memory: process.memoryUsage()
+ };
+ // Log health check for monitoring
+ console.log(`🏥 Health Check [${timestamp}]:`, {
+ status: healthData.status,
+ database: databaseStatus,
+ jwt_keys: jwtStatus.hasCurrentKey,
+ oauth: envCheck.google_client_id && envCheck.google_client_secret
+ });
+ res.status(isHealthy ? 200 : 503).json(healthData);
+}));
+// Data is now persisted using dataService - no more in-memory storage!
+// Admin password - MUST be set via environment variable in production
+const ADMIN_PASSWORD = process.env.ADMIN_PASSWORD || 'CHANGE_ME_ADMIN_PASSWORD';
+// Initialize flight tracking scheduler
+const flightTracker = new flightTrackingScheduler_1.default(flightService_1.default);
+// VIP routes (protected)
+app.post('/api/vips', simpleAuth_1.requireAuth, (0, simpleAuth_1.requireRole)(['coordinator', 'administrator']), (0, validation_1.validate)(schemas_1.createVipSchema), (0, errorHandler_1.asyncHandler)(async (req, res) => {
+ // Create a new VIP - data is already validated
+ const { name, organization, department, // New: Office of Development or Admin
+ transportMode, flightNumber, // Legacy single flight
+ flights, // New: array of flights
+ expectedArrival, needsAirportPickup, needsVenueTransport, notes } = req.body;
+ const newVip = {
+ id: Date.now().toString(), // Simple ID generation
+ name,
+ organization,
+ department: department || 'Office of Development', // Default to Office of Development
+ transportMode: transportMode || 'flight',
+ // Support both legacy single flight and new multiple flights
+ flightNumber: transportMode === 'flight' && !flights ? flightNumber : undefined,
+ flights: transportMode === 'flight' && flights ? flights : undefined,
+ expectedArrival: transportMode === 'self-driving' ? expectedArrival : undefined,
+ arrivalTime: transportMode === 'flight' ? undefined : expectedArrival, // Legacy field for flight arrivals
+ needsAirportPickup: transportMode === 'flight' ? (needsAirportPickup !== false) : false,
+ needsVenueTransport: needsVenueTransport !== false, // Default to true
+ assignedDriverIds: [],
+ notes: notes || '',
+ schedule: []
+ };
+ const savedVip = await enhancedDataService_1.default.addVip(newVip);
+ // Add flights to tracking scheduler if applicable
+ if (savedVip.transportMode === 'flight' && savedVip.flights && savedVip.flights.length > 0) {
+ flightTracker.addVipFlights(savedVip.id, savedVip.name, savedVip.flights);
+ }
+ res.status(201).json(savedVip);
+}));
+app.get('/api/vips', simpleAuth_1.requireAuth, async (req, res) => {
+ try {
+ // Fetch all VIPs
+ const vips = await enhancedDataService_1.default.getVips();
+ res.json(vips);
+ }
+ catch (error) {
+ res.status(500).json({ error: 'Failed to fetch VIPs' });
+ }
+});
+app.put('/api/vips/:id', simpleAuth_1.requireAuth, (0, simpleAuth_1.requireRole)(['coordinator', 'administrator']), (0, validation_1.validate)(schemas_1.updateVipSchema), (0, errorHandler_1.asyncHandler)(async (req, res) => {
+ // Update a VIP - data is already validated
+ const { id } = req.params;
+ const { name, organization, department, // New: Office of Development or Admin
+ transportMode, flightNumber, // Legacy single flight
+ flights, // New: array of flights
+ expectedArrival, needsAirportPickup, needsVenueTransport, notes } = req.body;
+ const updatedVip = {
+ name,
+ organization,
+ department: department || 'Office of Development',
+ transportMode: transportMode || 'flight',
+ // Support both legacy single flight and new multiple flights
+ flights: transportMode === 'flight' && flights ? flights : undefined,
+ expectedArrival: transportMode === 'self-driving' ? expectedArrival : undefined,
+ needsAirportPickup: transportMode === 'flight' ? (needsAirportPickup !== false) : false,
+ needsVenueTransport: needsVenueTransport !== false,
+ notes: notes || ''
+ };
+ const savedVip = await enhancedDataService_1.default.updateVip(id, updatedVip);
+ if (!savedVip) {
+ return res.status(404).json({ error: 'VIP not found' });
+ }
+ // Update flight tracking if needed
+ if (savedVip.transportMode === 'flight') {
+ // Remove old flights
+ flightTracker.removeVipFlights(id);
+ // Add new flights if any
+ if (savedVip.flights && savedVip.flights.length > 0) {
+ flightTracker.addVipFlights(savedVip.id, savedVip.name, savedVip.flights);
+ }
+ }
+ res.json(savedVip);
+}));
+app.delete('/api/vips/:id', simpleAuth_1.requireAuth, (0, simpleAuth_1.requireRole)(['coordinator', 'administrator']), async (req, res) => {
+ // Delete a VIP
+ const { id } = req.params;
+ try {
+ const deletedVip = await enhancedDataService_1.default.deleteVip(id);
+ if (!deletedVip) {
+ return res.status(404).json({ error: 'VIP not found' });
+ }
+ // Remove from flight tracking
+ flightTracker.removeVipFlights(id);
+ res.json({ message: 'VIP deleted successfully', vip: deletedVip });
+ }
+ catch (error) {
+ res.status(500).json({ error: 'Failed to delete VIP' });
+ }
+});
+// Driver routes (protected)
+app.post('/api/drivers', simpleAuth_1.requireAuth, (0, simpleAuth_1.requireRole)(['coordinator', 'administrator']), (0, validation_1.validate)(schemas_1.createDriverSchema), (0, errorHandler_1.asyncHandler)(async (req, res) => {
+ // Create a new driver - data is already validated
+ const { name, phone, email, vehicleInfo, status } = req.body;
+ const newDriver = {
+ id: Date.now().toString(),
+ name,
+ phone,
+ email,
+ vehicleInfo,
+ status: status || 'available',
+ department: 'Office of Development', // Default to Office of Development
+ currentLocation: { lat: 0, lng: 0 },
+ assignedVipIds: []
+ };
+ const savedDriver = await enhancedDataService_1.default.addDriver(newDriver);
+ res.status(201).json(savedDriver);
+}));
+app.get('/api/drivers', simpleAuth_1.requireAuth, async (req, res) => {
+ try {
+ // Fetch all drivers
+ const drivers = await enhancedDataService_1.default.getDrivers();
+ res.json(drivers);
+ }
+ catch (error) {
+ res.status(500).json({ error: 'Failed to fetch drivers' });
+ }
+});
+app.put('/api/drivers/:id', simpleAuth_1.requireAuth, (0, simpleAuth_1.requireRole)(['coordinator', 'administrator']), async (req, res) => {
+ // Update a driver
+ const { id } = req.params;
+ const { name, phone, currentLocation, department } = req.body;
+ try {
+ const updatedDriver = {
+ name,
+ phone,
+ department: department || 'Office of Development',
+ currentLocation: currentLocation || { lat: 0, lng: 0 }
+ };
+ const savedDriver = await enhancedDataService_1.default.updateDriver(id, updatedDriver);
+ if (!savedDriver) {
+ return res.status(404).json({ error: 'Driver not found' });
+ }
+ res.json(savedDriver);
+ }
+ catch (error) {
+ res.status(500).json({ error: 'Failed to update driver' });
+ }
+});
+app.delete('/api/drivers/:id', simpleAuth_1.requireAuth, (0, simpleAuth_1.requireRole)(['coordinator', 'administrator']), async (req, res) => {
+ // Delete a driver
+ const { id } = req.params;
+ try {
+ const deletedDriver = await enhancedDataService_1.default.deleteDriver(id);
+ if (!deletedDriver) {
+ return res.status(404).json({ error: 'Driver not found' });
+ }
+ res.json({ message: 'Driver deleted successfully', driver: deletedDriver });
+ }
+ catch (error) {
+ res.status(500).json({ error: 'Failed to delete driver' });
+ }
+});
+// Enhanced flight tracking routes with date specificity
+app.get('/api/flights/:flightNumber', async (req, res) => {
+ try {
+ const { flightNumber } = req.params;
+ const { date, departureAirport, arrivalAirport } = req.query;
+ // Default to today if no date provided
+ const flightDate = date || new Date().toISOString().split('T')[0];
+ const flightData = await flightService_1.default.getFlightInfo({
+ flightNumber,
+ date: flightDate,
+ departureAirport: departureAirport,
+ arrivalAirport: arrivalAirport
+ });
+ if (flightData) {
+ // Always return flight data for validation, even if date doesn't match
+ res.json(flightData);
+ }
+ else {
+ // Only return 404 if the flight number itself is invalid
+ res.status(404).json({ error: 'Invalid flight number - this flight does not exist' });
+ }
+ }
+ catch (error) {
+ res.status(500).json({ error: 'Failed to fetch flight data' });
+ }
+});
+// Start periodic updates for a flight
+app.post('/api/flights/:flightNumber/track', async (req, res) => {
+ try {
+ const { flightNumber } = req.params;
+ const { date, intervalMinutes = 5 } = req.body;
+ if (!date) {
+ return res.status(400).json({ error: 'Flight date is required' });
+ }
+ flightService_1.default.startPeriodicUpdates({
+ flightNumber,
+ date
+ }, intervalMinutes);
+ res.json({ message: `Started tracking ${flightNumber} on ${date}` });
+ }
+ catch (error) {
+ res.status(500).json({ error: 'Failed to start flight tracking' });
+ }
+});
+// Stop periodic updates for a flight
+app.delete('/api/flights/:flightNumber/track', async (req, res) => {
+ try {
+ const { flightNumber } = req.params;
+ const { date } = req.query;
+ if (!date) {
+ return res.status(400).json({ error: 'Flight date is required' });
+ }
+ const key = `${flightNumber}_${date}`;
+ flightService_1.default.stopPeriodicUpdates(key);
+ res.json({ message: `Stopped tracking ${flightNumber} on ${date}` });
+ }
+ catch (error) {
+ res.status(500).json({ error: 'Failed to stop flight tracking' });
+ }
+});
+app.post('/api/flights/batch', async (req, res) => {
+ try {
+ const { flights } = req.body;
+ if (!Array.isArray(flights)) {
+ return res.status(400).json({ error: 'flights must be an array of {flightNumber, date} objects' });
+ }
+ // Validate flight objects
+ for (const flight of flights) {
+ if (!flight.flightNumber || !flight.date) {
+ return res.status(400).json({ error: 'Each flight must have flightNumber and date' });
+ }
+ }
+ const flightData = await flightService_1.default.getMultipleFlights(flights);
+ res.json(flightData);
+ }
+ catch (error) {
+ res.status(500).json({ error: 'Failed to fetch flight data' });
+ }
+});
+// Get flight tracking status
+app.get('/api/flights/tracking/status', (req, res) => {
+ const status = flightTracker.getTrackingStatus();
+ res.json(status);
+});
+// Schedule management routes (protected)
+app.get('/api/vips/:vipId/schedule', simpleAuth_1.requireAuth, async (req, res) => {
+ const { vipId } = req.params;
+ try {
+ const vipSchedule = await enhancedDataService_1.default.getSchedule(vipId);
+ res.json(vipSchedule);
+ }
+ catch (error) {
+ res.status(500).json({ error: 'Failed to fetch schedule' });
+ }
+});
+app.post('/api/vips/:vipId/schedule', simpleAuth_1.requireAuth, (0, simpleAuth_1.requireRole)(['coordinator', 'administrator']), async (req, res) => {
+ const { vipId } = req.params;
+ const { title, location, startTime, endTime, description, type, assignedDriverId } = req.body;
+ // Validate the event
+ const validationErrors = scheduleValidationService_1.default.validateEvent({
+ title: title || '',
+ location: location || '',
+ startTime: startTime || '',
+ endTime: endTime || '',
+ type: type || ''
+ }, false);
+ const { critical, warnings } = scheduleValidationService_1.default.categorizeErrors(validationErrors);
+ // Return validation errors if any critical errors exist
+ if (critical.length > 0) {
+ return res.status(400).json({
+ error: 'Validation failed',
+ validationErrors: critical,
+ warnings: warnings,
+ message: scheduleValidationService_1.default.getErrorSummary(critical)
+ });
+ }
+ const newEvent = {
+ id: Date.now().toString(),
+ title,
+ location,
+ startTime,
+ endTime,
+ description: description || '',
+ assignedDriverId: assignedDriverId || '',
+ status: 'scheduled',
+ type
+ };
+ try {
+ const savedEvent = await enhancedDataService_1.default.addScheduleEvent(vipId, newEvent);
+ // Include warnings in the response if any
+ const response = { ...savedEvent };
+ if (warnings.length > 0) {
+ response.warnings = warnings;
+ }
+ res.status(201).json(response);
+ }
+ catch (error) {
+ res.status(500).json({ error: 'Failed to create schedule event' });
+ }
+});
+app.put('/api/vips/:vipId/schedule/:eventId', simpleAuth_1.requireAuth, (0, simpleAuth_1.requireRole)(['coordinator', 'administrator']), async (req, res) => {
+ const { vipId, eventId } = req.params;
+ const { title, location, startTime, endTime, description, type, assignedDriverId, status } = req.body;
+ // Validate the updated event (with edit flag for grace period)
+ const validationErrors = scheduleValidationService_1.default.validateEvent({
+ title: title || '',
+ location: location || '',
+ startTime: startTime || '',
+ endTime: endTime || '',
+ type: type || ''
+ }, true);
+ const { critical, warnings } = scheduleValidationService_1.default.categorizeErrors(validationErrors);
+ // Return validation errors if any critical errors exist
+ if (critical.length > 0) {
+ return res.status(400).json({
+ error: 'Validation failed',
+ validationErrors: critical,
+ warnings: warnings,
+ message: scheduleValidationService_1.default.getErrorSummary(critical)
+ });
+ }
+ const updatedEvent = {
+ id: eventId,
+ title,
+ location,
+ startTime,
+ endTime,
+ description: description || '',
+ assignedDriverId: assignedDriverId || '',
+ type,
+ status: status || 'scheduled'
+ };
+ try {
+ const savedEvent = await enhancedDataService_1.default.updateScheduleEvent(vipId, eventId, updatedEvent);
+ if (!savedEvent) {
+ return res.status(404).json({ error: 'Event not found' });
+ }
+ // Include warnings in the response if any
+ const response = { ...savedEvent };
+ if (warnings.length > 0) {
+ response.warnings = warnings;
+ }
+ res.json(response);
+ }
+ catch (error) {
+ res.status(500).json({ error: 'Failed to update schedule event' });
+ }
+});
+app.patch('/api/vips/:vipId/schedule/:eventId/status', simpleAuth_1.requireAuth, async (req, res) => {
+ const { vipId, eventId } = req.params;
+ const { status } = req.body;
+ try {
+ const currentSchedule = await enhancedDataService_1.default.getSchedule(vipId);
+ const currentEvent = currentSchedule.find((event) => event.id === eventId);
+ if (!currentEvent) {
+ return res.status(404).json({ error: 'Event not found' });
+ }
+ const updatedEvent = { ...currentEvent, status };
+ const savedEvent = await enhancedDataService_1.default.updateScheduleEvent(vipId, eventId, updatedEvent);
+ if (!savedEvent) {
+ return res.status(404).json({ error: 'Event not found' });
+ }
+ res.json(savedEvent);
+ }
+ catch (error) {
+ res.status(500).json({ error: 'Failed to update event status' });
+ }
+});
+app.delete('/api/vips/:vipId/schedule/:eventId', simpleAuth_1.requireAuth, (0, simpleAuth_1.requireRole)(['coordinator', 'administrator']), async (req, res) => {
+ const { vipId, eventId } = req.params;
+ try {
+ const deletedEvent = await enhancedDataService_1.default.deleteScheduleEvent(vipId, eventId);
+ if (!deletedEvent) {
+ return res.status(404).json({ error: 'Event not found' });
+ }
+ res.json({ message: 'Event deleted successfully', event: deletedEvent });
+ }
+ catch (error) {
+ res.status(500).json({ error: 'Failed to delete schedule event' });
+ }
+});
+// Driver availability and conflict checking (protected)
+app.post('/api/drivers/availability', simpleAuth_1.requireAuth, async (req, res) => {
+ const { startTime, endTime, location } = req.body;
+ if (!startTime || !endTime) {
+ return res.status(400).json({ error: 'startTime and endTime are required' });
+ }
+ try {
+ const allSchedules = await enhancedDataService_1.default.getAllSchedules();
+ const drivers = await enhancedDataService_1.default.getDrivers();
+ const availability = driverConflictService_1.default.getDriverAvailability({ startTime, endTime, location: location || '' }, allSchedules, drivers);
+ res.json(availability);
+ }
+ catch (error) {
+ res.status(500).json({ error: 'Failed to check driver availability' });
+ }
+});
+// Check conflicts for specific driver assignment (protected)
+app.post('/api/drivers/:driverId/conflicts', simpleAuth_1.requireAuth, async (req, res) => {
+ const { driverId } = req.params;
+ const { startTime, endTime, location } = req.body;
+ if (!startTime || !endTime) {
+ return res.status(400).json({ error: 'startTime and endTime are required' });
+ }
+ try {
+ const allSchedules = await enhancedDataService_1.default.getAllSchedules();
+ const drivers = await enhancedDataService_1.default.getDrivers();
+ const conflicts = driverConflictService_1.default.checkDriverConflicts(driverId, { startTime, endTime, location: location || '' }, allSchedules, drivers);
+ res.json({ conflicts });
+ }
+ catch (error) {
+ res.status(500).json({ error: 'Failed to check driver conflicts' });
+ }
+});
+// Get driver's complete schedule (protected)
+app.get('/api/drivers/:driverId/schedule', simpleAuth_1.requireAuth, async (req, res) => {
+ const { driverId } = req.params;
+ try {
+ const drivers = await enhancedDataService_1.default.getDrivers();
+ const driver = drivers.find((d) => d.id === driverId);
+ if (!driver) {
+ return res.status(404).json({ error: 'Driver not found' });
+ }
+ // Get all events assigned to this driver across all VIPs
+ const driverSchedule = [];
+ const allSchedules = await enhancedDataService_1.default.getAllSchedules();
+ const vips = await enhancedDataService_1.default.getVips();
+ Object.entries(allSchedules).forEach(([vipId, events]) => {
+ events.forEach((event) => {
+ if (event.assignedDriverId === driverId) {
+ // Get VIP name
+ const vip = vips.find((v) => v.id === vipId);
+ driverSchedule.push({
+ ...event,
+ vipId,
+ vipName: vip ? vip.name : 'Unknown VIP'
+ });
+ }
+ });
+ });
+ // Sort by start time
+ driverSchedule.sort((a, b) => new Date(a.startTime).getTime() - new Date(b.startTime).getTime());
+ res.json({
+ driver: {
+ id: driver.id,
+ name: driver.name,
+ phone: driver.phone,
+ department: driver.department
+ },
+ schedule: driverSchedule
+ });
+ }
+ catch (error) {
+ res.status(500).json({ error: 'Failed to fetch driver schedule' });
+ }
+});
+// Admin routes
+app.post('/api/admin/authenticate', (req, res) => {
+ const { password } = req.body;
+ if (password === ADMIN_PASSWORD) {
+ res.json({ success: true });
+ }
+ else {
+ res.status(401).json({ error: 'Invalid password' });
+ }
+});
+app.get('/api/admin/settings', async (req, res) => {
+ const adminAuth = req.headers['admin-auth'];
+ if (adminAuth !== 'true') {
+ return res.status(401).json({ error: 'Unauthorized' });
+ }
+ try {
+ const adminSettings = await enhancedDataService_1.default.getAdminSettings();
+ // Return settings but mask API keys for display only
+ // IMPORTANT: Don't return the actual keys, just indicate they exist
+ const maskedSettings = {
+ apiKeys: {
+ aviationStackKey: adminSettings.apiKeys.aviationStackKey ? '***' + adminSettings.apiKeys.aviationStackKey.slice(-4) : '',
+ googleMapsKey: adminSettings.apiKeys.googleMapsKey ? '***' + adminSettings.apiKeys.googleMapsKey.slice(-4) : '',
+ twilioKey: adminSettings.apiKeys.twilioKey ? '***' + adminSettings.apiKeys.twilioKey.slice(-4) : '',
+ googleClientId: adminSettings.apiKeys.googleClientId ? '***' + adminSettings.apiKeys.googleClientId.slice(-4) : '',
+ googleClientSecret: adminSettings.apiKeys.googleClientSecret ? '***' + adminSettings.apiKeys.googleClientSecret.slice(-4) : ''
+ },
+ systemSettings: adminSettings.systemSettings
+ };
+ res.json(maskedSettings);
+ }
+ catch (error) {
+ res.status(500).json({ error: 'Failed to fetch admin settings' });
+ }
+});
+app.post('/api/admin/settings', async (req, res) => {
+ const adminAuth = req.headers['admin-auth'];
+ if (adminAuth !== 'true') {
+ return res.status(401).json({ error: 'Unauthorized' });
+ }
+ try {
+ const { apiKeys, systemSettings } = req.body;
+ const currentSettings = await enhancedDataService_1.default.getAdminSettings();
+ // Update API keys (only if provided and not masked)
+ if (apiKeys) {
+ if (apiKeys.aviationStackKey && !apiKeys.aviationStackKey.startsWith('***')) {
+ currentSettings.apiKeys.aviationStackKey = apiKeys.aviationStackKey;
+ // Update the environment variable for the flight service
+ process.env.AVIATIONSTACK_API_KEY = apiKeys.aviationStackKey;
+ }
+ if (apiKeys.googleMapsKey && !apiKeys.googleMapsKey.startsWith('***')) {
+ currentSettings.apiKeys.googleMapsKey = apiKeys.googleMapsKey;
+ }
+ if (apiKeys.twilioKey && !apiKeys.twilioKey.startsWith('***')) {
+ currentSettings.apiKeys.twilioKey = apiKeys.twilioKey;
+ }
+ if (apiKeys.googleClientId && !apiKeys.googleClientId.startsWith('***')) {
+ currentSettings.apiKeys.googleClientId = apiKeys.googleClientId;
+ // Update the environment variable for Google OAuth
+ process.env.GOOGLE_CLIENT_ID = apiKeys.googleClientId;
+ }
+ if (apiKeys.googleClientSecret && !apiKeys.googleClientSecret.startsWith('***')) {
+ currentSettings.apiKeys.googleClientSecret = apiKeys.googleClientSecret;
+ // Update the environment variable for Google OAuth
+ process.env.GOOGLE_CLIENT_SECRET = apiKeys.googleClientSecret;
+ }
+ }
+ // Update system settings
+ if (systemSettings) {
+ currentSettings.systemSettings = { ...currentSettings.systemSettings, ...systemSettings };
+ }
+ // Save the updated settings
+ await enhancedDataService_1.default.updateAdminSettings(currentSettings);
+ res.json({ success: true });
+ }
+ catch (error) {
+ res.status(500).json({ error: 'Failed to update admin settings' });
+ }
+});
+app.post('/api/admin/test-api/:apiType', async (req, res) => {
+ const adminAuth = req.headers['admin-auth'];
+ if (adminAuth !== 'true') {
+ return res.status(401).json({ error: 'Unauthorized' });
+ }
+ const { apiType } = req.params;
+ const { apiKey } = req.body;
+ try {
+ switch (apiType) {
+ case 'aviationStackKey':
+ // Test AviationStack API
+ const testUrl = `http://api.aviationstack.com/v1/flights?access_key=${apiKey}&limit=1`;
+ const response = await fetch(testUrl);
+ if (response.ok) {
+ const data = await response.json();
+ if (data.error) {
+ res.status(400).json({ error: data.error.message || 'Invalid API key' });
+ }
+ else {
+ res.json({ success: true, message: 'API key is valid!' });
+ }
+ }
+ else {
+ res.status(400).json({ error: 'Failed to validate API key' });
+ }
+ break;
+ case 'googleMapsKey':
+ res.json({ success: true, message: 'Google Maps API testing not yet implemented' });
+ break;
+ case 'twilioKey':
+ res.json({ success: true, message: 'Twilio API testing not yet implemented' });
+ break;
+ default:
+ res.status(400).json({ error: 'Unknown API type' });
+ }
+ }
+ catch (error) {
+ res.status(500).json({ error: 'Failed to test API connection' });
+ }
+});
+// JWT Key Management endpoints (admin only)
+app.get('/api/admin/jwt-status', simpleAuth_1.requireAuth, (0, simpleAuth_1.requireRole)(['administrator']), (req, res) => {
+ const jwtKeyManager = require('./services/jwtKeyManager').default;
+ const status = jwtKeyManager.getStatus();
+ res.json({
+ keyRotationEnabled: true,
+ rotationInterval: '24 hours',
+ gracePeriod: '24 hours',
+ ...status,
+ message: 'JWT keys are automatically rotated every 24 hours for enhanced security'
+ });
+});
+app.post('/api/admin/jwt-rotate', simpleAuth_1.requireAuth, (0, simpleAuth_1.requireRole)(['administrator']), (req, res) => {
+ const jwtKeyManager = require('./services/jwtKeyManager').default;
+ try {
+ jwtKeyManager.forceRotation();
+ res.json({
+ success: true,
+ message: 'JWT key rotation triggered successfully. New tokens will use the new key.'
+ });
+ }
+ catch (error) {
+ res.status(500).json({ error: 'Failed to rotate JWT keys' });
+ }
+});
+// Initialize database and start server
+// Add 404 handler for undefined routes
+app.use(errorHandler_1.notFoundHandler);
+// Add error logging middleware
+app.use(logger_1.errorLogger);
+// Add global error handler (must be last!)
+app.use(errorHandler_1.errorHandler);
+async function startServer() {
+ try {
+ // Initialize database schema and migrate data
+ await databaseService_1.default.initializeDatabase();
+ console.log('✅ Database initialization completed');
+ // Start the server
+ app.listen(port, () => {
+ console.log(`🚀 Server is running on port ${port}`);
+ console.log(`🔐 Admin password: ${ADMIN_PASSWORD}`);
+ console.log(`📊 Admin dashboard: http://localhost:${port === 3000 ? 5173 : port}/admin`);
+ console.log(`🏥 Health check: http://localhost:${port}/api/health`);
+ console.log(`📚 API docs: http://localhost:${port}/api-docs.html`);
+ });
+ }
+ catch (error) {
+ console.error('❌ Failed to start server:', error);
+ process.exit(1);
+ }
+}
+startServer();
+//# sourceMappingURL=index.original.js.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/index.original.js.map b/backend-old-20260125/dist/index.original.js.map
new file mode 100644
index 0000000..c6b2110
--- /dev/null
+++ b/backend-old-20260125/dist/index.original.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.original.js","sourceRoot":"","sources":["../src/index.original.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/indexSimplified.d.ts b/backend-old-20260125/dist/indexSimplified.d.ts
new file mode 100644
index 0000000..808bcb9
--- /dev/null
+++ b/backend-old-20260125/dist/indexSimplified.d.ts
@@ -0,0 +1,2 @@
+export {};
+//# sourceMappingURL=indexSimplified.d.ts.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/indexSimplified.d.ts.map b/backend-old-20260125/dist/indexSimplified.d.ts.map
new file mode 100644
index 0000000..31178b1
--- /dev/null
+++ b/backend-old-20260125/dist/indexSimplified.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"indexSimplified.d.ts","sourceRoot":"","sources":["../src/indexSimplified.ts"],"names":[],"mappings":""}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/indexSimplified.js b/backend-old-20260125/dist/indexSimplified.js
new file mode 100644
index 0000000..eed46d8
--- /dev/null
+++ b/backend-old-20260125/dist/indexSimplified.js
@@ -0,0 +1,217 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const express_1 = __importDefault(require("express"));
+const cors_1 = __importDefault(require("cors"));
+const dotenv_1 = __importDefault(require("dotenv"));
+const authService_1 = __importDefault(require("./services/authService"));
+const unifiedDataService_1 = __importDefault(require("./services/unifiedDataService"));
+const simpleValidation_1 = require("./middleware/simpleValidation");
+const errorHandler_1 = require("./middleware/errorHandler");
+dotenv_1.default.config();
+const app = (0, express_1.default)();
+const port = process.env.PORT || 3000;
+// Middleware
+app.use((0, cors_1.default)({
+ origin: [
+ process.env.FRONTEND_URL || 'http://localhost:5173',
+ 'https://bsa.madeamess.online'
+ ],
+ credentials: true
+}));
+app.use(express_1.default.json());
+app.use(express_1.default.static('public'));
+// Health check
+app.get('/api/health', (req, res) => {
+ res.json({
+ status: 'OK',
+ timestamp: new Date().toISOString(),
+ version: '2.0.0' // Simplified version
+ });
+});
+// Auth routes
+app.get('/auth/google', (req, res) => {
+ res.redirect(authService_1.default.getGoogleAuthUrl());
+});
+app.post('/auth/google/callback', async (req, res) => {
+ try {
+ const { code } = req.body;
+ const { user, token } = await authService_1.default.handleGoogleAuth(code);
+ res.json({ user, token });
+ }
+ catch (error) {
+ res.status(400).json({ error: 'Authentication failed' });
+ }
+});
+app.get('/auth/me', authService_1.default.requireAuth, (req, res) => {
+ res.json(req.user);
+});
+app.post('/auth/logout', (req, res) => {
+ res.json({ message: 'Logged out successfully' });
+});
+// VIP routes
+app.get('/api/vips', authService_1.default.requireAuth, async (req, res, next) => {
+ try {
+ const vips = await unifiedDataService_1.default.getVips();
+ res.json(vips);
+ }
+ catch (error) {
+ next(error);
+ }
+});
+app.get('/api/vips/:id', authService_1.default.requireAuth, async (req, res, next) => {
+ try {
+ const vip = await unifiedDataService_1.default.getVipById(req.params.id);
+ if (!vip)
+ return res.status(404).json({ error: 'VIP not found' });
+ res.json(vip);
+ }
+ catch (error) {
+ next(error);
+ }
+});
+app.post('/api/vips', authService_1.default.requireAuth, authService_1.default.requireRole(['coordinator', 'administrator']), (0, simpleValidation_1.validate)(simpleValidation_1.schemas.createVip), async (req, res, next) => {
+ try {
+ const vip = await unifiedDataService_1.default.createVip(req.body);
+ res.status(201).json(vip);
+ }
+ catch (error) {
+ next(error);
+ }
+});
+app.put('/api/vips/:id', authService_1.default.requireAuth, authService_1.default.requireRole(['coordinator', 'administrator']), (0, simpleValidation_1.validate)(simpleValidation_1.schemas.updateVip), async (req, res, next) => {
+ try {
+ const vip = await unifiedDataService_1.default.updateVip(req.params.id, req.body);
+ if (!vip)
+ return res.status(404).json({ error: 'VIP not found' });
+ res.json(vip);
+ }
+ catch (error) {
+ next(error);
+ }
+});
+app.delete('/api/vips/:id', authService_1.default.requireAuth, authService_1.default.requireRole(['coordinator', 'administrator']), async (req, res, next) => {
+ try {
+ const vip = await unifiedDataService_1.default.deleteVip(req.params.id);
+ if (!vip)
+ return res.status(404).json({ error: 'VIP not found' });
+ res.json({ message: 'VIP deleted successfully' });
+ }
+ catch (error) {
+ next(error);
+ }
+});
+// Driver routes
+app.get('/api/drivers', authService_1.default.requireAuth, async (req, res, next) => {
+ try {
+ const drivers = await unifiedDataService_1.default.getDrivers();
+ res.json(drivers);
+ }
+ catch (error) {
+ next(error);
+ }
+});
+app.post('/api/drivers', authService_1.default.requireAuth, authService_1.default.requireRole(['coordinator', 'administrator']), (0, simpleValidation_1.validate)(simpleValidation_1.schemas.createDriver), async (req, res, next) => {
+ try {
+ const driver = await unifiedDataService_1.default.createDriver(req.body);
+ res.status(201).json(driver);
+ }
+ catch (error) {
+ next(error);
+ }
+});
+app.put('/api/drivers/:id', authService_1.default.requireAuth, authService_1.default.requireRole(['coordinator', 'administrator']), (0, simpleValidation_1.validate)(simpleValidation_1.schemas.updateDriver), async (req, res, next) => {
+ try {
+ const driver = await unifiedDataService_1.default.updateDriver(req.params.id, req.body);
+ if (!driver)
+ return res.status(404).json({ error: 'Driver not found' });
+ res.json(driver);
+ }
+ catch (error) {
+ next(error);
+ }
+});
+app.delete('/api/drivers/:id', authService_1.default.requireAuth, authService_1.default.requireRole(['coordinator', 'administrator']), async (req, res, next) => {
+ try {
+ const driver = await unifiedDataService_1.default.deleteDriver(req.params.id);
+ if (!driver)
+ return res.status(404).json({ error: 'Driver not found' });
+ res.json({ message: 'Driver deleted successfully' });
+ }
+ catch (error) {
+ next(error);
+ }
+});
+// Schedule routes
+app.get('/api/vips/:vipId/schedule', authService_1.default.requireAuth, async (req, res, next) => {
+ try {
+ const schedule = await unifiedDataService_1.default.getScheduleByVipId(req.params.vipId);
+ res.json(schedule);
+ }
+ catch (error) {
+ next(error);
+ }
+});
+app.post('/api/vips/:vipId/schedule', authService_1.default.requireAuth, authService_1.default.requireRole(['coordinator', 'administrator']), (0, simpleValidation_1.validate)(simpleValidation_1.schemas.createScheduleEvent), async (req, res, next) => {
+ try {
+ const event = await unifiedDataService_1.default.createScheduleEvent(req.params.vipId, req.body);
+ res.status(201).json(event);
+ }
+ catch (error) {
+ next(error);
+ }
+});
+app.put('/api/vips/:vipId/schedule/:eventId', authService_1.default.requireAuth, authService_1.default.requireRole(['coordinator', 'administrator']), (0, simpleValidation_1.validate)(simpleValidation_1.schemas.updateScheduleEvent), async (req, res, next) => {
+ try {
+ const event = await unifiedDataService_1.default.updateScheduleEvent(req.params.eventId, req.body);
+ if (!event)
+ return res.status(404).json({ error: 'Event not found' });
+ res.json(event);
+ }
+ catch (error) {
+ next(error);
+ }
+});
+app.delete('/api/vips/:vipId/schedule/:eventId', authService_1.default.requireAuth, authService_1.default.requireRole(['coordinator', 'administrator']), async (req, res, next) => {
+ try {
+ const event = await unifiedDataService_1.default.deleteScheduleEvent(req.params.eventId);
+ if (!event)
+ return res.status(404).json({ error: 'Event not found' });
+ res.json({ message: 'Event deleted successfully' });
+ }
+ catch (error) {
+ next(error);
+ }
+});
+// Admin routes (simplified)
+app.get('/api/admin/settings', authService_1.default.requireAuth, authService_1.default.requireRole(['administrator']), async (req, res, next) => {
+ try {
+ const settings = await unifiedDataService_1.default.getAdminSettings();
+ res.json(settings);
+ }
+ catch (error) {
+ next(error);
+ }
+});
+app.post('/api/admin/settings', authService_1.default.requireAuth, authService_1.default.requireRole(['administrator']), async (req, res, next) => {
+ try {
+ const { key, value } = req.body;
+ await unifiedDataService_1.default.updateAdminSetting(key, value);
+ res.json({ message: 'Setting updated successfully' });
+ }
+ catch (error) {
+ next(error);
+ }
+});
+// Error handling
+app.use(errorHandler_1.notFoundHandler);
+app.use(errorHandler_1.errorHandler);
+// Start server
+app.listen(port, () => {
+ console.log(`🚀 Server running on port ${port}`);
+ console.log(`🏥 Health check: http://localhost:${port}/api/health`);
+ console.log(`📚 API docs: http://localhost:${port}/api-docs.html`);
+});
+//# sourceMappingURL=indexSimplified.js.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/indexSimplified.js.map b/backend-old-20260125/dist/indexSimplified.js.map
new file mode 100644
index 0000000..974936d
--- /dev/null
+++ b/backend-old-20260125/dist/indexSimplified.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"indexSimplified.js","sourceRoot":"","sources":["../src/indexSimplified.ts"],"names":[],"mappings":";;;;;AAAA,sDAA8B;AAC9B,gDAAwB;AACxB,oDAA4B;AAC5B,yEAAiD;AACjD,uFAAwD;AACxD,oEAAkE;AAClE,4DAA0E;AAE1E,gBAAM,CAAC,MAAM,EAAE,CAAC;AAEhB,MAAM,GAAG,GAAG,IAAA,iBAAO,GAAE,CAAC;AACtB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC;AAEtC,aAAa;AACb,GAAG,CAAC,GAAG,CAAC,IAAA,cAAI,EAAC;IACX,MAAM,EAAE;QACN,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,uBAAuB;QACnD,8BAA8B;KAC/B;IACD,WAAW,EAAE,IAAI;CAClB,CAAC,CAAC,CAAC;AACJ,GAAG,CAAC,GAAG,CAAC,iBAAO,CAAC,IAAI,EAAE,CAAC,CAAC;AACxB,GAAG,CAAC,GAAG,CAAC,iBAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;AAElC,eAAe;AACf,GAAG,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;IAClC,GAAG,CAAC,IAAI,CAAC;QACP,MAAM,EAAE,IAAI;QACZ,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,OAAO,EAAE,OAAO,CAAC,qBAAqB;KACvC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,cAAc;AACd,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;IACnC,GAAG,CAAC,QAAQ,CAAC,qBAAW,CAAC,gBAAgB,EAAE,CAAC,CAAC;AAC/C,CAAC,CAAC,CAAC;AAEH,GAAG,CAAC,IAAI,CAAC,uBAAuB,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;IACnD,IAAI,CAAC;QACH,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC;QAC1B,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,qBAAW,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACjE,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC5B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,GAAG,CAAC,GAAG,CAAC,UAAU,EAAE,qBAAW,CAAC,WAAW,EAAE,CAAC,GAAQ,EAAE,GAAG,EAAE,EAAE;IAC7D,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACrB,CAAC,CAAC,CAAC;AAEH,GAAG,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;IACpC,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,yBAAyB,EAAE,CAAC,CAAC;AACnD,CAAC,CAAC,CAAC;AAEH,aAAa;AACb,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,qBAAW,CAAC,WAAW,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;IACrE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,4BAAW,CAAC,OAAO,EAAE,CAAC;QACzC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,KAAK,CAAC,CAAC;IACd,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,GAAG,CAAC,GAAG,CAAC,eAAe,EAAE,qBAAW,CAAC,WAAW,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;IACzE,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,4BAAW,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACxD,IAAI,CAAC,GAAG;YAAE,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC,CAAC;QAClE,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,KAAK,CAAC,CAAC;IACd,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,GAAG,CAAC,IAAI,CAAC,WAAW,EAClB,qBAAW,CAAC,WAAW,EACvB,qBAAW,CAAC,WAAW,CAAC,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC,EACzD,IAAA,2BAAQ,EAAC,0BAAO,CAAC,SAAS,CAAC,EAC3B,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;IACvB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,4BAAW,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,KAAK,CAAC,CAAC;IACd,CAAC;AACH,CAAC,CACF,CAAC;AAEF,GAAG,CAAC,GAAG,CAAC,eAAe,EACrB,qBAAW,CAAC,WAAW,EACvB,qBAAW,CAAC,WAAW,CAAC,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC,EACzD,IAAA,2BAAQ,EAAC,0BAAO,CAAC,SAAS,CAAC,EAC3B,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;IACvB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,4BAAW,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QACjE,IAAI,CAAC,GAAG;YAAE,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC,CAAC;QAClE,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,KAAK,CAAC,CAAC;IACd,CAAC;AACH,CAAC,CACF,CAAC;AAEF,GAAG,CAAC,MAAM,CAAC,eAAe,EACxB,qBAAW,CAAC,WAAW,EACvB,qBAAW,CAAC,WAAW,CAAC,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC,EACzD,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;IACvB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,4BAAW,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACvD,IAAI,CAAC,GAAG;YAAE,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC,CAAC;QAClE,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,0BAA0B,EAAE,CAAC,CAAC;IACpD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,KAAK,CAAC,CAAC;IACd,CAAC;AACH,CAAC,CACF,CAAC;AAEF,gBAAgB;AAChB,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,qBAAW,CAAC,WAAW,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;IACxE,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,4BAAW,CAAC,UAAU,EAAE,CAAC;QAC/C,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,KAAK,CAAC,CAAC;IACd,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,GAAG,CAAC,IAAI,CAAC,cAAc,EACrB,qBAAW,CAAC,WAAW,EACvB,qBAAW,CAAC,WAAW,CAAC,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC,EACzD,IAAA,2BAAQ,EAAC,0BAAO,CAAC,YAAY,CAAC,EAC9B,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;IACvB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,4BAAW,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACxD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,KAAK,CAAC,CAAC;IACd,CAAC;AACH,CAAC,CACF,CAAC;AAEF,GAAG,CAAC,GAAG,CAAC,kBAAkB,EACxB,qBAAW,CAAC,WAAW,EACvB,qBAAW,CAAC,WAAW,CAAC,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC,EACzD,IAAA,2BAAQ,EAAC,0BAAO,CAAC,YAAY,CAAC,EAC9B,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;IACvB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,4BAAW,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QACvE,IAAI,CAAC,MAAM;YAAE,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC,CAAC;QACxE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACnB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,KAAK,CAAC,CAAC;IACd,CAAC;AACH,CAAC,CACF,CAAC;AAEF,GAAG,CAAC,MAAM,CAAC,kBAAkB,EAC3B,qBAAW,CAAC,WAAW,EACvB,qBAAW,CAAC,WAAW,CAAC,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC,EACzD,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;IACvB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,4BAAW,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC7D,IAAI,CAAC,MAAM;YAAE,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC,CAAC;QACxE,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,6BAA6B,EAAE,CAAC,CAAC;IACvD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,KAAK,CAAC,CAAC;IACd,CAAC;AACH,CAAC,CACF,CAAC;AAEF,kBAAkB;AAClB,GAAG,CAAC,GAAG,CAAC,2BAA2B,EAAE,qBAAW,CAAC,WAAW,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;IACrF,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,4BAAW,CAAC,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACxE,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACrB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,KAAK,CAAC,CAAC;IACd,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,GAAG,CAAC,IAAI,CAAC,2BAA2B,EAClC,qBAAW,CAAC,WAAW,EACvB,qBAAW,CAAC,WAAW,CAAC,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC,EACzD,IAAA,2BAAQ,EAAC,0BAAO,CAAC,mBAAmB,CAAC,EACrC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;IACvB,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,4BAAW,CAAC,mBAAmB,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QAChF,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,KAAK,CAAC,CAAC;IACd,CAAC;AACH,CAAC,CACF,CAAC;AAEF,GAAG,CAAC,GAAG,CAAC,oCAAoC,EAC1C,qBAAW,CAAC,WAAW,EACvB,qBAAW,CAAC,WAAW,CAAC,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC,EACzD,IAAA,2BAAQ,EAAC,0BAAO,CAAC,mBAAmB,CAAC,EACrC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;IACvB,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,4BAAW,CAAC,mBAAmB,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QAClF,IAAI,CAAC,KAAK;YAAE,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC,CAAC;QACtE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,KAAK,CAAC,CAAC;IACd,CAAC;AACH,CAAC,CACF,CAAC;AAEF,GAAG,CAAC,MAAM,CAAC,oCAAoC,EAC7C,qBAAW,CAAC,WAAW,EACvB,qBAAW,CAAC,WAAW,CAAC,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC,EACzD,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;IACvB,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,4BAAW,CAAC,mBAAmB,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACxE,IAAI,CAAC,KAAK;YAAE,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC,CAAC;QACtE,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,4BAA4B,EAAE,CAAC,CAAC;IACtD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,KAAK,CAAC,CAAC;IACd,CAAC;AACH,CAAC,CACF,CAAC;AAEF,4BAA4B;AAC5B,GAAG,CAAC,GAAG,CAAC,qBAAqB,EAC3B,qBAAW,CAAC,WAAW,EACvB,qBAAW,CAAC,WAAW,CAAC,CAAC,eAAe,CAAC,CAAC,EAC1C,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;IACvB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,4BAAW,CAAC,gBAAgB,EAAE,CAAC;QACtD,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACrB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,KAAK,CAAC,CAAC;IACd,CAAC;AACH,CAAC,CACF,CAAC;AAEF,GAAG,CAAC,IAAI,CAAC,qBAAqB,EAC5B,qBAAW,CAAC,WAAW,EACvB,qBAAW,CAAC,WAAW,CAAC,CAAC,eAAe,CAAC,CAAC,EAC1C,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;IACvB,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC;QAChC,MAAM,4BAAW,CAAC,kBAAkB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACjD,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,8BAA8B,EAAE,CAAC,CAAC;IACxD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,KAAK,CAAC,CAAC;IACd,CAAC;AACH,CAAC,CACF,CAAC;AAEF,iBAAiB;AACjB,GAAG,CAAC,GAAG,CAAC,8BAAe,CAAC,CAAC;AACzB,GAAG,CAAC,GAAG,CAAC,2BAAY,CAAC,CAAC;AAEtB,eAAe;AACf,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;IACpB,OAAO,CAAC,GAAG,CAAC,6BAA6B,IAAI,EAAE,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,qCAAqC,IAAI,aAAa,CAAC,CAAC;IACpE,OAAO,CAAC,GAAG,CAAC,iCAAiC,IAAI,gBAAgB,CAAC,CAAC;AACrE,CAAC,CAAC,CAAC"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/middleware/errorHandler.d.ts b/backend-old-20260125/dist/middleware/errorHandler.d.ts
new file mode 100644
index 0000000..14388ea
--- /dev/null
+++ b/backend-old-20260125/dist/middleware/errorHandler.d.ts
@@ -0,0 +1,6 @@
+import { Request, Response, NextFunction } from 'express';
+import { AppError } from '../types/errors';
+export declare const errorHandler: (err: Error | AppError, req: Request, res: Response, next: NextFunction) => void;
+export declare const asyncHandler: (fn: Function) => (req: Request, res: Response, next: NextFunction) => void;
+export declare const notFoundHandler: (req: Request, res: Response) => void;
+//# sourceMappingURL=errorHandler.d.ts.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/middleware/errorHandler.d.ts.map b/backend-old-20260125/dist/middleware/errorHandler.d.ts.map
new file mode 100644
index 0000000..65e0124
--- /dev/null
+++ b/backend-old-20260125/dist/middleware/errorHandler.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"errorHandler.d.ts","sourceRoot":"","sources":["../../src/middleware/errorHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAiB,MAAM,iBAAiB,CAAC;AAE1D,eAAO,MAAM,YAAY,GACvB,KAAK,KAAK,GAAG,QAAQ,EACrB,KAAK,OAAO,EACZ,KAAK,QAAQ,EACb,MAAM,YAAY,KACjB,IA+CF,CAAC;AAGF,eAAO,MAAM,YAAY,GAAI,IAAI,QAAQ,MAC/B,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,SAGxD,CAAC;AAGF,eAAO,MAAM,eAAe,GAAI,KAAK,OAAO,EAAE,KAAK,QAAQ,KAAG,IAY7D,CAAC"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/middleware/errorHandler.js b/backend-old-20260125/dist/middleware/errorHandler.js
new file mode 100644
index 0000000..8f9ffe7
--- /dev/null
+++ b/backend-old-20260125/dist/middleware/errorHandler.js
@@ -0,0 +1,75 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.notFoundHandler = exports.asyncHandler = exports.errorHandler = void 0;
+const errors_1 = require("../types/errors");
+const errorHandler = (err, req, res, next) => {
+ // Default error values
+ let statusCode = 500;
+ let message = 'Internal server error';
+ let isOperational = false;
+ // If it's an AppError, use its properties
+ if (err instanceof errors_1.AppError) {
+ statusCode = err.statusCode;
+ message = err.message;
+ isOperational = err.isOperational;
+ }
+ else if (err.name === 'ValidationError') {
+ // Handle validation errors (e.g., from libraries)
+ statusCode = 400;
+ message = err.message;
+ isOperational = true;
+ }
+ else if (err.name === 'JsonWebTokenError') {
+ statusCode = 401;
+ message = 'Invalid token';
+ isOperational = true;
+ }
+ else if (err.name === 'TokenExpiredError') {
+ statusCode = 401;
+ message = 'Token expired';
+ isOperational = true;
+ }
+ // Log error details (in production, use proper logging service)
+ if (!isOperational) {
+ console.error('ERROR 💥:', err);
+ }
+ else {
+ console.error(`Operational error: ${message}`);
+ }
+ // Create error response
+ const errorResponse = {
+ success: false,
+ error: {
+ message,
+ ...(process.env.NODE_ENV === 'development' && {
+ details: err.stack
+ })
+ },
+ timestamp: new Date().toISOString(),
+ path: req.path
+ };
+ res.status(statusCode).json(errorResponse);
+};
+exports.errorHandler = errorHandler;
+// Async error wrapper to catch errors in async route handlers
+const asyncHandler = (fn) => {
+ return (req, res, next) => {
+ Promise.resolve(fn(req, res, next)).catch(next);
+ };
+};
+exports.asyncHandler = asyncHandler;
+// 404 Not Found handler
+const notFoundHandler = (req, res) => {
+ const errorResponse = {
+ success: false,
+ error: {
+ message: `Route ${req.originalUrl} not found`,
+ code: 'ROUTE_NOT_FOUND'
+ },
+ timestamp: new Date().toISOString(),
+ path: req.path
+ };
+ res.status(404).json(errorResponse);
+};
+exports.notFoundHandler = notFoundHandler;
+//# sourceMappingURL=errorHandler.js.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/middleware/errorHandler.js.map b/backend-old-20260125/dist/middleware/errorHandler.js.map
new file mode 100644
index 0000000..7829f15
--- /dev/null
+++ b/backend-old-20260125/dist/middleware/errorHandler.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"errorHandler.js","sourceRoot":"","sources":["../../src/middleware/errorHandler.ts"],"names":[],"mappings":";;;AACA,4CAA0D;AAEnD,MAAM,YAAY,GAAG,CAC1B,GAAqB,EACrB,GAAY,EACZ,GAAa,EACb,IAAkB,EACZ,EAAE;IACR,uBAAuB;IACvB,IAAI,UAAU,GAAG,GAAG,CAAC;IACrB,IAAI,OAAO,GAAG,uBAAuB,CAAC;IACtC,IAAI,aAAa,GAAG,KAAK,CAAC;IAE1B,0CAA0C;IAC1C,IAAI,GAAG,YAAY,iBAAQ,EAAE,CAAC;QAC5B,UAAU,GAAG,GAAG,CAAC,UAAU,CAAC;QAC5B,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;QACtB,aAAa,GAAG,GAAG,CAAC,aAAa,CAAC;IACpC,CAAC;SAAM,IAAI,GAAG,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;QAC1C,kDAAkD;QAClD,UAAU,GAAG,GAAG,CAAC;QACjB,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;QACtB,aAAa,GAAG,IAAI,CAAC;IACvB,CAAC;SAAM,IAAI,GAAG,CAAC,IAAI,KAAK,mBAAmB,EAAE,CAAC;QAC5C,UAAU,GAAG,GAAG,CAAC;QACjB,OAAO,GAAG,eAAe,CAAC;QAC1B,aAAa,GAAG,IAAI,CAAC;IACvB,CAAC;SAAM,IAAI,GAAG,CAAC,IAAI,KAAK,mBAAmB,EAAE,CAAC;QAC5C,UAAU,GAAG,GAAG,CAAC;QACjB,OAAO,GAAG,eAAe,CAAC;QAC1B,aAAa,GAAG,IAAI,CAAC;IACvB,CAAC;IAED,gEAAgE;IAChE,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;IAClC,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,sBAAsB,OAAO,EAAE,CAAC,CAAC;IACjD,CAAC;IAED,wBAAwB;IACxB,MAAM,aAAa,GAAkB;QACnC,OAAO,EAAE,KAAK;QACd,KAAK,EAAE;YACL,OAAO;YACP,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,IAAI;gBAC5C,OAAO,EAAE,GAAG,CAAC,KAAK;aACnB,CAAC;SACH;QACD,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,IAAI,EAAE,GAAG,CAAC,IAAI;KACf,CAAC;IAEF,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;AAC7C,CAAC,CAAC;AApDW,QAAA,YAAY,gBAoDvB;AAEF,8DAA8D;AACvD,MAAM,YAAY,GAAG,CAAC,EAAY,EAAE,EAAE;IAC3C,OAAO,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;QACzD,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClD,CAAC,CAAC;AACJ,CAAC,CAAC;AAJW,QAAA,YAAY,gBAIvB;AAEF,wBAAwB;AACjB,MAAM,eAAe,GAAG,CAAC,GAAY,EAAE,GAAa,EAAQ,EAAE;IACnE,MAAM,aAAa,GAAkB;QACnC,OAAO,EAAE,KAAK;QACd,KAAK,EAAE;YACL,OAAO,EAAE,SAAS,GAAG,CAAC,WAAW,YAAY;YAC7C,IAAI,EAAE,iBAAiB;SACxB;QACD,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,IAAI,EAAE,GAAG,CAAC,IAAI;KACf,CAAC;IAEF,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;AACtC,CAAC,CAAC;AAZW,QAAA,eAAe,mBAY1B"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/middleware/logger.d.ts b/backend-old-20260125/dist/middleware/logger.d.ts
new file mode 100644
index 0000000..f282c11
--- /dev/null
+++ b/backend-old-20260125/dist/middleware/logger.d.ts
@@ -0,0 +1,15 @@
+import { Request, Response, NextFunction } from 'express';
+declare module 'express' {
+ interface Request {
+ requestId?: string;
+ user?: {
+ id: string;
+ email: string;
+ name: string;
+ role: string;
+ };
+ }
+}
+export declare const requestLogger: (req: Request, res: Response, next: NextFunction) => void;
+export declare const errorLogger: (err: Error, req: Request, res: Response, next: NextFunction) => void;
+//# sourceMappingURL=logger.d.ts.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/middleware/logger.d.ts.map b/backend-old-20260125/dist/middleware/logger.d.ts.map
new file mode 100644
index 0000000..95a53c2
--- /dev/null
+++ b/backend-old-20260125/dist/middleware/logger.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/middleware/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAa1D,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAU,OAAO;QACf,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,IAAI,CAAC,EAAE;YACL,EAAE,EAAE,MAAM,CAAC;YACX,KAAK,EAAE,MAAM,CAAC;YACd,IAAI,EAAE,MAAM,CAAC;YACb,IAAI,EAAE,MAAM,CAAC;SACd,CAAC;KACH;CACF;AAQD,eAAO,MAAM,aAAa,GAAI,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,KAAG,IAkC/E,CAAC;AAGF,eAAO,MAAM,WAAW,GAAI,KAAK,KAAK,EAAE,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,KAAG,IAmBzF,CAAC"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/middleware/logger.js b/backend-old-20260125/dist/middleware/logger.js
new file mode 100644
index 0000000..816f567
--- /dev/null
+++ b/backend-old-20260125/dist/middleware/logger.js
@@ -0,0 +1,58 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.errorLogger = exports.requestLogger = void 0;
+// Generate a simple request ID
+const generateRequestId = () => {
+ return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
+};
+// Request logger middleware
+const requestLogger = (req, res, next) => {
+ const requestId = generateRequestId();
+ // Attach request ID to request object
+ req.requestId = requestId;
+ const startTime = Date.now();
+ // Log request
+ const logContext = {
+ requestId,
+ method: req.method,
+ url: req.originalUrl,
+ ip: req.ip || 'unknown',
+ userAgent: req.get('user-agent'),
+ userId: req.user?.id
+ };
+ console.log(`[${new Date().toISOString()}] REQUEST:`, JSON.stringify(logContext));
+ // Log response
+ const originalSend = res.send;
+ res.send = function (data) {
+ const duration = Date.now() - startTime;
+ console.log(`[${new Date().toISOString()}] RESPONSE:`, JSON.stringify({
+ requestId,
+ statusCode: res.statusCode,
+ duration: `${duration}ms`
+ }));
+ return originalSend.call(this, data);
+ };
+ next();
+};
+exports.requestLogger = requestLogger;
+// Error logger (to be used before error handler)
+const errorLogger = (err, req, res, next) => {
+ const requestId = req.requestId || 'unknown';
+ console.error(`[${new Date().toISOString()}] ERROR:`, JSON.stringify({
+ requestId,
+ error: {
+ name: err.name,
+ message: err.message,
+ stack: err.stack
+ },
+ request: {
+ method: req.method,
+ url: req.originalUrl,
+ headers: req.headers,
+ body: req.body
+ }
+ }));
+ next(err);
+};
+exports.errorLogger = errorLogger;
+//# sourceMappingURL=logger.js.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/middleware/logger.js.map b/backend-old-20260125/dist/middleware/logger.js.map
new file mode 100644
index 0000000..c6e5f4d
--- /dev/null
+++ b/backend-old-20260125/dist/middleware/logger.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/middleware/logger.ts"],"names":[],"mappings":";;;AAyBA,+BAA+B;AAC/B,MAAM,iBAAiB,GAAG,GAAW,EAAE;IACrC,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;AACpE,CAAC,CAAC;AAEF,4BAA4B;AACrB,MAAM,aAAa,GAAG,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAQ,EAAE;IACrF,MAAM,SAAS,GAAG,iBAAiB,EAAE,CAAC;IAEtC,sCAAsC;IACtC,GAAG,CAAC,SAAS,GAAG,SAAS,CAAC;IAE1B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,cAAc;IACd,MAAM,UAAU,GAAe;QAC7B,SAAS;QACT,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,GAAG,EAAE,GAAG,CAAC,WAAW;QACpB,EAAE,EAAE,GAAG,CAAC,EAAE,IAAI,SAAS;QACvB,SAAS,EAAE,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC;QAChC,MAAM,EAAE,GAAG,CAAC,IAAI,EAAE,EAAE;KACrB,CAAC;IAEF,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC;IAElF,eAAe;IACf,MAAM,YAAY,GAAG,GAAG,CAAC,IAAI,CAAC;IAC9B,GAAG,CAAC,IAAI,GAAG,UAAS,IAAa;QAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;QACxC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC;YACpE,SAAS;YACT,UAAU,EAAE,GAAG,CAAC,UAAU;YAC1B,QAAQ,EAAE,GAAG,QAAQ,IAAI;SAC1B,CAAC,CAAC,CAAC;QAEJ,OAAO,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACvC,CAAC,CAAC;IAEF,IAAI,EAAE,CAAC;AACT,CAAC,CAAC;AAlCW,QAAA,aAAa,iBAkCxB;AAEF,iDAAiD;AAC1C,MAAM,WAAW,GAAG,CAAC,GAAU,EAAE,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAQ,EAAE;IAC/F,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,IAAI,SAAS,CAAC;IAE7C,OAAO,CAAC,KAAK,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC;QACnE,SAAS;QACT,KAAK,EAAE;YACL,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,KAAK,EAAE,GAAG,CAAC,KAAK;SACjB;QACD,OAAO,EAAE;YACP,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,GAAG,EAAE,GAAG,CAAC,WAAW;YACpB,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,IAAI,EAAE,GAAG,CAAC,IAAI;SACf;KACF,CAAC,CAAC,CAAC;IAEJ,IAAI,CAAC,GAAG,CAAC,CAAC;AACZ,CAAC,CAAC;AAnBW,QAAA,WAAW,eAmBtB"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/middleware/simpleValidation.d.ts b/backend-old-20260125/dist/middleware/simpleValidation.d.ts
new file mode 100644
index 0000000..175b4ee
--- /dev/null
+++ b/backend-old-20260125/dist/middleware/simpleValidation.d.ts
@@ -0,0 +1,197 @@
+import { z } from 'zod';
+import { Request, Response, NextFunction } from 'express';
+export declare const schemas: {
+ createVip: z.ZodObject<{
+ name: z.ZodString;
+ organization: z.ZodOptional;
+ department: z.ZodDefault>;
+ transportMode: z.ZodDefault>;
+ flights: z.ZodOptional;
+ scheduledArrival: z.ZodString;
+ scheduledDeparture: z.ZodOptional;
+ }, "strip", z.ZodTypeAny, {
+ flightNumber: string;
+ scheduledArrival: string;
+ airline?: string | undefined;
+ scheduledDeparture?: string | undefined;
+ }, {
+ flightNumber: string;
+ scheduledArrival: string;
+ airline?: string | undefined;
+ scheduledDeparture?: string | undefined;
+ }>, "many">>;
+ expectedArrival: z.ZodOptional;
+ needsAirportPickup: z.ZodDefault;
+ needsVenueTransport: z.ZodDefault;
+ notes: z.ZodOptional;
+ }, "strip", z.ZodTypeAny, {
+ name: string;
+ department: "Office of Development" | "Admin";
+ transportMode: "flight" | "self-driving";
+ needsAirportPickup: boolean;
+ needsVenueTransport: boolean;
+ organization?: string | undefined;
+ flights?: {
+ flightNumber: string;
+ scheduledArrival: string;
+ airline?: string | undefined;
+ scheduledDeparture?: string | undefined;
+ }[] | undefined;
+ expectedArrival?: string | undefined;
+ notes?: string | undefined;
+ }, {
+ name: string;
+ organization?: string | undefined;
+ department?: "Office of Development" | "Admin" | undefined;
+ transportMode?: "flight" | "self-driving" | undefined;
+ flights?: {
+ flightNumber: string;
+ scheduledArrival: string;
+ airline?: string | undefined;
+ scheduledDeparture?: string | undefined;
+ }[] | undefined;
+ expectedArrival?: string | undefined;
+ needsAirportPickup?: boolean | undefined;
+ needsVenueTransport?: boolean | undefined;
+ notes?: string | undefined;
+ }>;
+ updateVip: z.ZodObject<{
+ name: z.ZodOptional;
+ organization: z.ZodOptional;
+ department: z.ZodOptional>;
+ transportMode: z.ZodOptional>;
+ flights: z.ZodOptional;
+ scheduledArrival: z.ZodString;
+ scheduledDeparture: z.ZodOptional;
+ }, "strip", z.ZodTypeAny, {
+ flightNumber: string;
+ scheduledArrival: string;
+ airline?: string | undefined;
+ scheduledDeparture?: string | undefined;
+ }, {
+ flightNumber: string;
+ scheduledArrival: string;
+ airline?: string | undefined;
+ scheduledDeparture?: string | undefined;
+ }>, "many">>;
+ expectedArrival: z.ZodOptional;
+ needsAirportPickup: z.ZodOptional;
+ needsVenueTransport: z.ZodOptional;
+ notes: z.ZodOptional;
+ }, "strip", z.ZodTypeAny, {
+ name?: string | undefined;
+ organization?: string | undefined;
+ department?: "Office of Development" | "Admin" | undefined;
+ transportMode?: "flight" | "self-driving" | undefined;
+ flights?: {
+ flightNumber: string;
+ scheduledArrival: string;
+ airline?: string | undefined;
+ scheduledDeparture?: string | undefined;
+ }[] | undefined;
+ expectedArrival?: string | undefined;
+ needsAirportPickup?: boolean | undefined;
+ needsVenueTransport?: boolean | undefined;
+ notes?: string | undefined;
+ }, {
+ name?: string | undefined;
+ organization?: string | undefined;
+ department?: "Office of Development" | "Admin" | undefined;
+ transportMode?: "flight" | "self-driving" | undefined;
+ flights?: {
+ flightNumber: string;
+ scheduledArrival: string;
+ airline?: string | undefined;
+ scheduledDeparture?: string | undefined;
+ }[] | undefined;
+ expectedArrival?: string | undefined;
+ needsAirportPickup?: boolean | undefined;
+ needsVenueTransport?: boolean | undefined;
+ notes?: string | undefined;
+ }>;
+ createDriver: z.ZodObject<{
+ name: z.ZodString;
+ email: z.ZodOptional;
+ phone: z.ZodString;
+ vehicleInfo: z.ZodOptional;
+ status: z.ZodDefault>;
+ }, "strip", z.ZodTypeAny, {
+ name: string;
+ phone: string;
+ status: "available" | "assigned" | "unavailable";
+ email?: string | undefined;
+ vehicleInfo?: string | undefined;
+ }, {
+ name: string;
+ phone: string;
+ email?: string | undefined;
+ vehicleInfo?: string | undefined;
+ status?: "available" | "assigned" | "unavailable" | undefined;
+ }>;
+ updateDriver: z.ZodObject<{
+ name: z.ZodOptional;
+ email: z.ZodOptional;
+ phone: z.ZodOptional;
+ vehicleInfo: z.ZodOptional;
+ status: z.ZodOptional>;
+ }, "strip", z.ZodTypeAny, {
+ name?: string | undefined;
+ email?: string | undefined;
+ phone?: string | undefined;
+ vehicleInfo?: string | undefined;
+ status?: "available" | "assigned" | "unavailable" | undefined;
+ }, {
+ name?: string | undefined;
+ email?: string | undefined;
+ phone?: string | undefined;
+ vehicleInfo?: string | undefined;
+ status?: "available" | "assigned" | "unavailable" | undefined;
+ }>;
+ createScheduleEvent: z.ZodObject<{
+ driverId: z.ZodOptional;
+ eventTime: z.ZodString;
+ eventType: z.ZodEnum<["pickup", "dropoff", "custom"]>;
+ location: z.ZodString;
+ notes: z.ZodOptional;
+ }, "strip", z.ZodTypeAny, {
+ eventTime: string;
+ eventType: "custom" | "pickup" | "dropoff";
+ location: string;
+ notes?: string | undefined;
+ driverId?: string | undefined;
+ }, {
+ eventTime: string;
+ eventType: "custom" | "pickup" | "dropoff";
+ location: string;
+ notes?: string | undefined;
+ driverId?: string | undefined;
+ }>;
+ updateScheduleEvent: z.ZodObject<{
+ driverId: z.ZodOptional;
+ eventTime: z.ZodOptional;
+ eventType: z.ZodOptional>;
+ location: z.ZodOptional;
+ notes: z.ZodOptional;
+ status: z.ZodOptional>;
+ }, "strip", z.ZodTypeAny, {
+ notes?: string | undefined;
+ status?: "scheduled" | "in_progress" | "completed" | "cancelled" | undefined;
+ driverId?: string | undefined;
+ eventTime?: string | undefined;
+ eventType?: "custom" | "pickup" | "dropoff" | undefined;
+ location?: string | undefined;
+ }, {
+ notes?: string | undefined;
+ status?: "scheduled" | "in_progress" | "completed" | "cancelled" | undefined;
+ driverId?: string | undefined;
+ eventTime?: string | undefined;
+ eventType?: "custom" | "pickup" | "dropoff" | undefined;
+ location?: string | undefined;
+ }>;
+};
+export declare const validate: (schema: z.ZodSchema) => (req: Request, res: Response, next: NextFunction) => Promise> | undefined>;
+//# sourceMappingURL=simpleValidation.d.ts.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/middleware/simpleValidation.d.ts.map b/backend-old-20260125/dist/middleware/simpleValidation.d.ts.map
new file mode 100644
index 0000000..44c92a1
--- /dev/null
+++ b/backend-old-20260125/dist/middleware/simpleValidation.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"simpleValidation.d.ts","sourceRoot":"","sources":["../../src/middleware/simpleValidation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAG1D,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsEnB,CAAC;AAGF,eAAO,MAAM,QAAQ,GAAI,QAAQ,CAAC,CAAC,SAAS,MAC5B,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,4DAc9D,CAAC"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/middleware/simpleValidation.js b/backend-old-20260125/dist/middleware/simpleValidation.js
new file mode 100644
index 0000000..4bee2d0
--- /dev/null
+++ b/backend-old-20260125/dist/middleware/simpleValidation.js
@@ -0,0 +1,91 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.validate = exports.schemas = void 0;
+const zod_1 = require("zod");
+// Simplified validation schemas - removed unnecessary complexity
+exports.schemas = {
+ // VIP schemas
+ createVip: zod_1.z.object({
+ name: zod_1.z.string().min(1).max(100),
+ organization: zod_1.z.string().max(100).optional(),
+ department: zod_1.z.enum(['Office of Development', 'Admin']).default('Office of Development'),
+ transportMode: zod_1.z.enum(['flight', 'self-driving']).default('flight'),
+ flights: zod_1.z.array(zod_1.z.object({
+ flightNumber: zod_1.z.string(),
+ airline: zod_1.z.string().optional(),
+ scheduledArrival: zod_1.z.string(),
+ scheduledDeparture: zod_1.z.string().optional()
+ })).optional(),
+ expectedArrival: zod_1.z.string().optional(),
+ needsAirportPickup: zod_1.z.boolean().default(true),
+ needsVenueTransport: zod_1.z.boolean().default(true),
+ notes: zod_1.z.string().max(500).optional()
+ }),
+ updateVip: zod_1.z.object({
+ name: zod_1.z.string().min(1).max(100).optional(),
+ organization: zod_1.z.string().max(100).optional(),
+ department: zod_1.z.enum(['Office of Development', 'Admin']).optional(),
+ transportMode: zod_1.z.enum(['flight', 'self-driving']).optional(),
+ flights: zod_1.z.array(zod_1.z.object({
+ flightNumber: zod_1.z.string(),
+ airline: zod_1.z.string().optional(),
+ scheduledArrival: zod_1.z.string(),
+ scheduledDeparture: zod_1.z.string().optional()
+ })).optional(),
+ expectedArrival: zod_1.z.string().optional(),
+ needsAirportPickup: zod_1.z.boolean().optional(),
+ needsVenueTransport: zod_1.z.boolean().optional(),
+ notes: zod_1.z.string().max(500).optional()
+ }),
+ // Driver schemas
+ createDriver: zod_1.z.object({
+ name: zod_1.z.string().min(1).max(100),
+ email: zod_1.z.string().email().optional(),
+ phone: zod_1.z.string(),
+ vehicleInfo: zod_1.z.string().max(200).optional(),
+ status: zod_1.z.enum(['available', 'assigned', 'unavailable']).default('available')
+ }),
+ updateDriver: zod_1.z.object({
+ name: zod_1.z.string().min(1).max(100).optional(),
+ email: zod_1.z.string().email().optional(),
+ phone: zod_1.z.string().optional(),
+ vehicleInfo: zod_1.z.string().max(200).optional(),
+ status: zod_1.z.enum(['available', 'assigned', 'unavailable']).optional()
+ }),
+ // Schedule schemas
+ createScheduleEvent: zod_1.z.object({
+ driverId: zod_1.z.string().optional(),
+ eventTime: zod_1.z.string(),
+ eventType: zod_1.z.enum(['pickup', 'dropoff', 'custom']),
+ location: zod_1.z.string().min(1).max(200),
+ notes: zod_1.z.string().max(500).optional()
+ }),
+ updateScheduleEvent: zod_1.z.object({
+ driverId: zod_1.z.string().optional(),
+ eventTime: zod_1.z.string().optional(),
+ eventType: zod_1.z.enum(['pickup', 'dropoff', 'custom']).optional(),
+ location: zod_1.z.string().min(1).max(200).optional(),
+ notes: zod_1.z.string().max(500).optional(),
+ status: zod_1.z.enum(['scheduled', 'in_progress', 'completed', 'cancelled']).optional()
+ })
+};
+// Single validation middleware
+const validate = (schema) => {
+ return async (req, res, next) => {
+ try {
+ req.body = await schema.parseAsync(req.body);
+ next();
+ }
+ catch (error) {
+ if (error instanceof zod_1.z.ZodError) {
+ const message = error.errors
+ .map(err => `${err.path.join('.')}: ${err.message}`)
+ .join(', ');
+ return res.status(400).json({ error: message });
+ }
+ next(error);
+ }
+ };
+};
+exports.validate = validate;
+//# sourceMappingURL=simpleValidation.js.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/middleware/simpleValidation.js.map b/backend-old-20260125/dist/middleware/simpleValidation.js.map
new file mode 100644
index 0000000..835419d
--- /dev/null
+++ b/backend-old-20260125/dist/middleware/simpleValidation.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"simpleValidation.js","sourceRoot":"","sources":["../../src/middleware/simpleValidation.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/middleware/validation.d.ts b/backend-old-20260125/dist/middleware/validation.d.ts
new file mode 100644
index 0000000..90bd31a
--- /dev/null
+++ b/backend-old-20260125/dist/middleware/validation.d.ts
@@ -0,0 +1,6 @@
+import { Request, Response, NextFunction } from 'express';
+import { z } from 'zod';
+export declare const validate: (schema: z.ZodSchema) => (req: Request, res: Response, next: NextFunction) => Promise;
+export declare const validateQuery: (schema: z.ZodSchema) => (req: Request, res: Response, next: NextFunction) => Promise;
+export declare const validateParams: (schema: z.ZodSchema) => (req: Request, res: Response, next: NextFunction) => Promise;
+//# sourceMappingURL=validation.d.ts.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/middleware/validation.d.ts.map b/backend-old-20260125/dist/middleware/validation.d.ts.map
new file mode 100644
index 0000000..81cd54a
--- /dev/null
+++ b/backend-old-20260125/dist/middleware/validation.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/middleware/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC1D,OAAO,EAAE,CAAC,EAAY,MAAM,KAAK,CAAC;AAGlC,eAAO,MAAM,QAAQ,GAAI,QAAQ,CAAC,CAAC,SAAS,MAC5B,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,kBAqB9D,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,QAAQ,CAAC,CAAC,SAAS,MACjC,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,kBAqB9D,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,QAAQ,CAAC,CAAC,SAAS,MAClC,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,kBAqB9D,CAAC"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/middleware/validation.js b/backend-old-20260125/dist/middleware/validation.js
new file mode 100644
index 0000000..be858d7
--- /dev/null
+++ b/backend-old-20260125/dist/middleware/validation.js
@@ -0,0 +1,78 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.validateParams = exports.validateQuery = exports.validate = void 0;
+const zod_1 = require("zod");
+const errors_1 = require("../types/errors");
+const validate = (schema) => {
+ return async (req, res, next) => {
+ try {
+ // Validate request body
+ req.body = await schema.parseAsync(req.body);
+ next();
+ }
+ catch (error) {
+ if (error instanceof zod_1.ZodError) {
+ // Format Zod errors into a user-friendly message
+ const errors = error.errors.map(err => ({
+ field: err.path.join('.'),
+ message: err.message
+ }));
+ const message = errors.map(e => `${e.field}: ${e.message}`).join(', ');
+ next(new errors_1.ValidationError(message));
+ }
+ else {
+ next(error);
+ }
+ }
+ };
+};
+exports.validate = validate;
+const validateQuery = (schema) => {
+ return async (req, res, next) => {
+ try {
+ // Validate query parameters
+ req.query = await schema.parseAsync(req.query);
+ next();
+ }
+ catch (error) {
+ if (error instanceof zod_1.ZodError) {
+ // Format Zod errors into a user-friendly message
+ const errors = error.errors.map(err => ({
+ field: err.path.join('.'),
+ message: err.message
+ }));
+ const message = errors.map(e => `${e.field}: ${e.message}`).join(', ');
+ next(new errors_1.ValidationError(`Invalid query parameters: ${message}`));
+ }
+ else {
+ next(error);
+ }
+ }
+ };
+};
+exports.validateQuery = validateQuery;
+const validateParams = (schema) => {
+ return async (req, res, next) => {
+ try {
+ // Validate route parameters
+ req.params = await schema.parseAsync(req.params);
+ next();
+ }
+ catch (error) {
+ if (error instanceof zod_1.ZodError) {
+ // Format Zod errors into a user-friendly message
+ const errors = error.errors.map(err => ({
+ field: err.path.join('.'),
+ message: err.message
+ }));
+ const message = errors.map(e => `${e.field}: ${e.message}`).join(', ');
+ next(new errors_1.ValidationError(`Invalid route parameters: ${message}`));
+ }
+ else {
+ next(error);
+ }
+ }
+ };
+};
+exports.validateParams = validateParams;
+//# sourceMappingURL=validation.js.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/middleware/validation.js.map b/backend-old-20260125/dist/middleware/validation.js.map
new file mode 100644
index 0000000..478ebf3
--- /dev/null
+++ b/backend-old-20260125/dist/middleware/validation.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/middleware/validation.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/routes/simpleAuth.d.ts b/backend-old-20260125/dist/routes/simpleAuth.d.ts
new file mode 100644
index 0000000..a5762b4
--- /dev/null
+++ b/backend-old-20260125/dist/routes/simpleAuth.d.ts
@@ -0,0 +1,6 @@
+import express, { Request, Response, NextFunction } from 'express';
+declare const router: import("express-serve-static-core").Router;
+export declare function requireAuth(req: Request, res: Response, next: NextFunction): express.Response> | undefined;
+export declare function requireRole(roles: string[]): (req: Request, res: Response, next: NextFunction) => express.Response> | undefined;
+export default router;
+//# sourceMappingURL=simpleAuth.d.ts.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/routes/simpleAuth.d.ts.map b/backend-old-20260125/dist/routes/simpleAuth.d.ts.map
new file mode 100644
index 0000000..4c6b000
--- /dev/null
+++ b/backend-old-20260125/dist/routes/simpleAuth.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"simpleAuth.d.ts","sourceRoot":"","sources":["../../src/routes/simpleAuth.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAWnE,QAAA,MAAM,MAAM,4CAAmB,CAAC;AA8ChC,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,0DAwD1E;AAGD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,IACjC,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,4DASxD;AAseD,eAAe,MAAM,CAAC"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/routes/simpleAuth.js b/backend-old-20260125/dist/routes/simpleAuth.js
new file mode 100644
index 0000000..6973aec
--- /dev/null
+++ b/backend-old-20260125/dist/routes/simpleAuth.js
@@ -0,0 +1,534 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.requireAuth = requireAuth;
+exports.requireRole = requireRole;
+const express_1 = __importDefault(require("express"));
+const simpleAuth_1 = require("../config/simpleAuth");
+const databaseService_1 = __importDefault(require("../services/databaseService"));
+const router = express_1.default.Router();
+// Enhanced logging for production debugging
+function logAuthEvent(event, details = {}) {
+ const timestamp = new Date().toISOString();
+ console.log(`🔐 [AUTH ${timestamp}] ${event}:`, JSON.stringify(details, null, 2));
+}
+// Validate environment variables on startup
+function validateAuthEnvironment() {
+ const required = ['GOOGLE_CLIENT_ID', 'GOOGLE_CLIENT_SECRET', 'GOOGLE_REDIRECT_URI', 'FRONTEND_URL'];
+ const missing = required.filter(key => !process.env[key]);
+ if (missing.length > 0) {
+ logAuthEvent('ENVIRONMENT_ERROR', { missing_variables: missing });
+ return false;
+ }
+ // Validate URLs
+ const frontendUrl = process.env.FRONTEND_URL;
+ const redirectUri = process.env.GOOGLE_REDIRECT_URI;
+ if (!frontendUrl?.startsWith('http')) {
+ logAuthEvent('ENVIRONMENT_ERROR', { error: 'FRONTEND_URL must start with http/https' });
+ return false;
+ }
+ if (!redirectUri?.startsWith('http')) {
+ logAuthEvent('ENVIRONMENT_ERROR', { error: 'GOOGLE_REDIRECT_URI must start with http/https' });
+ return false;
+ }
+ logAuthEvent('ENVIRONMENT_VALIDATED', {
+ frontend_url: frontendUrl,
+ redirect_uri: redirectUri,
+ client_id_configured: !!process.env.GOOGLE_CLIENT_ID,
+ client_secret_configured: !!process.env.GOOGLE_CLIENT_SECRET
+ });
+ return true;
+}
+// Validate environment on module load
+const isEnvironmentValid = validateAuthEnvironment();
+// Middleware to check authentication
+function requireAuth(req, res, next) {
+ try {
+ const authHeader = req.headers.authorization;
+ if (!authHeader || !authHeader.startsWith('Bearer ')) {
+ logAuthEvent('AUTH_FAILED', {
+ reason: 'no_token',
+ ip: req.ip,
+ path: req.path,
+ headers_present: !!req.headers.authorization
+ });
+ return res.status(401).json({ error: 'No token provided' });
+ }
+ const token = authHeader.substring(7);
+ if (!token || token.length < 10) {
+ logAuthEvent('AUTH_FAILED', {
+ reason: 'invalid_token_format',
+ ip: req.ip,
+ path: req.path,
+ token_length: token?.length || 0
+ });
+ return res.status(401).json({ error: 'Invalid token format' });
+ }
+ const user = (0, simpleAuth_1.verifyToken)(token);
+ if (!user) {
+ logAuthEvent('AUTH_FAILED', {
+ reason: 'token_verification_failed',
+ ip: req.ip,
+ path: req.path,
+ token_prefix: token.substring(0, 10) + '...'
+ });
+ return res.status(401).json({ error: 'Invalid or expired token' });
+ }
+ logAuthEvent('AUTH_SUCCESS', {
+ user_id: user.id,
+ user_email: user.email,
+ user_role: user.role,
+ ip: req.ip,
+ path: req.path
+ });
+ req.user = user;
+ next();
+ }
+ catch (error) {
+ logAuthEvent('AUTH_ERROR', {
+ error: error instanceof Error ? error.message : 'Unknown error',
+ ip: req.ip,
+ path: req.path
+ });
+ return res.status(500).json({ error: 'Authentication system error' });
+ }
+}
+// Middleware to check role
+function requireRole(roles) {
+ return (req, res, next) => {
+ const user = req.user;
+ if (!user || !roles.includes(user.role)) {
+ return res.status(403).json({ error: 'Insufficient permissions' });
+ }
+ next();
+ };
+}
+// Get current user
+router.get('/me', requireAuth, (req, res) => {
+ res.json(req.user);
+});
+// Setup status endpoint (required by frontend)
+router.get('/setup', async (req, res) => {
+ try {
+ const clientId = process.env.GOOGLE_CLIENT_ID;
+ const clientSecret = process.env.GOOGLE_CLIENT_SECRET;
+ const redirectUri = process.env.GOOGLE_REDIRECT_URI;
+ const frontendUrl = process.env.FRONTEND_URL;
+ logAuthEvent('SETUP_CHECK', {
+ client_id_present: !!clientId,
+ client_secret_present: !!clientSecret,
+ redirect_uri_present: !!redirectUri,
+ frontend_url_present: !!frontendUrl,
+ environment_valid: isEnvironmentValid
+ });
+ // Check database connectivity
+ let userCount = 0;
+ let databaseConnected = false;
+ try {
+ userCount = await databaseService_1.default.getUserCount();
+ databaseConnected = true;
+ logAuthEvent('DATABASE_CHECK', { status: 'connected', user_count: userCount });
+ }
+ catch (dbError) {
+ logAuthEvent('DATABASE_ERROR', {
+ error: dbError instanceof Error ? dbError.message : 'Unknown database error'
+ });
+ return res.status(500).json({
+ error: 'Database connection failed',
+ details: 'Cannot connect to PostgreSQL database'
+ });
+ }
+ const setupCompleted = !!(clientId &&
+ clientSecret &&
+ redirectUri &&
+ frontendUrl &&
+ clientId !== 'your-google-client-id-from-console' &&
+ clientId !== 'your-google-client-id' &&
+ isEnvironmentValid);
+ const response = {
+ setupCompleted,
+ firstAdminCreated: userCount > 0,
+ oauthConfigured: !!(clientId && clientSecret),
+ databaseConnected,
+ environmentValid: isEnvironmentValid,
+ configuration: {
+ google_oauth: !!(clientId && clientSecret),
+ redirect_uri_configured: !!redirectUri,
+ frontend_url_configured: !!frontendUrl,
+ production_ready: setupCompleted && databaseConnected
+ }
+ };
+ logAuthEvent('SETUP_STATUS', response);
+ res.json(response);
+ }
+ catch (error) {
+ logAuthEvent('SETUP_ERROR', {
+ error: error instanceof Error ? error.message : 'Unknown setup error'
+ });
+ res.status(500).json({
+ error: 'Setup check failed',
+ details: error instanceof Error ? error.message : 'Unknown error'
+ });
+ }
+});
+// Start Google OAuth flow
+router.get('/google', (req, res) => {
+ try {
+ const authUrl = (0, simpleAuth_1.getGoogleAuthUrl)();
+ res.redirect(authUrl);
+ }
+ catch (error) {
+ console.error('Error starting Google OAuth:', error);
+ const frontendUrl = process.env.FRONTEND_URL || 'http://localhost:5173';
+ res.redirect(`${frontendUrl}?error=oauth_not_configured`);
+ }
+});
+// Handle Google OAuth callback (this is where Google redirects back to)
+router.get('/google/callback', async (req, res) => {
+ const { code, error, state } = req.query;
+ const frontendUrl = process.env.FRONTEND_URL || 'http://localhost:5173';
+ logAuthEvent('OAUTH_CALLBACK', {
+ has_code: !!code,
+ has_error: !!error,
+ error_type: error,
+ state,
+ frontend_url: frontendUrl,
+ ip: req.ip,
+ user_agent: req.get('User-Agent')
+ });
+ // Validate environment before proceeding
+ if (!isEnvironmentValid) {
+ logAuthEvent('OAUTH_CALLBACK_ERROR', { reason: 'invalid_environment' });
+ return res.redirect(`${frontendUrl}?error=configuration_error&message=OAuth not properly configured`);
+ }
+ if (error) {
+ logAuthEvent('OAUTH_ERROR', { error, ip: req.ip });
+ return res.redirect(`${frontendUrl}?error=${error}&message=OAuth authorization failed`);
+ }
+ if (!code) {
+ logAuthEvent('OAUTH_ERROR', { reason: 'no_authorization_code', ip: req.ip });
+ return res.redirect(`${frontendUrl}?error=no_code&message=No authorization code received`);
+ }
+ try {
+ logAuthEvent('OAUTH_TOKEN_EXCHANGE_START', { code_length: code.length });
+ // Exchange code for tokens
+ const tokens = await (0, simpleAuth_1.exchangeCodeForTokens)(code);
+ if (!tokens || !tokens.access_token) {
+ logAuthEvent('OAUTH_TOKEN_EXCHANGE_FAILED', { tokens_received: !!tokens });
+ return res.redirect(`${frontendUrl}?error=token_exchange_failed&message=Failed to exchange authorization code`);
+ }
+ logAuthEvent('OAUTH_TOKEN_EXCHANGE_SUCCESS', { has_access_token: !!tokens.access_token });
+ // Get user info
+ const googleUser = await (0, simpleAuth_1.getGoogleUserInfo)(tokens.access_token);
+ if (!googleUser || !googleUser.email) {
+ logAuthEvent('OAUTH_USER_INFO_FAILED', { user_data: !!googleUser });
+ return res.redirect(`${frontendUrl}?error=user_info_failed&message=Failed to get user information from Google`);
+ }
+ logAuthEvent('OAUTH_USER_INFO_SUCCESS', {
+ email: googleUser.email,
+ name: googleUser.name,
+ verified_email: googleUser.verified_email
+ });
+ // Check if user exists or create new user
+ let user = await databaseService_1.default.getUserByEmail(googleUser.email);
+ if (!user) {
+ // Determine role - first user becomes admin, others need approval
+ const approvedUserCount = await databaseService_1.default.getApprovedUserCount();
+ const role = approvedUserCount === 0 ? 'administrator' : 'coordinator';
+ logAuthEvent('USER_CREATION', {
+ email: googleUser.email,
+ role,
+ is_first_user: approvedUserCount === 0
+ });
+ user = await databaseService_1.default.createUser({
+ id: googleUser.id,
+ google_id: googleUser.id,
+ email: googleUser.email,
+ name: googleUser.name,
+ profile_picture_url: googleUser.picture,
+ role
+ });
+ // Auto-approve first admin, others need approval
+ if (approvedUserCount === 0) {
+ await databaseService_1.default.updateUserApprovalStatus(googleUser.email, 'approved');
+ user.approval_status = 'approved';
+ logAuthEvent('FIRST_ADMIN_CREATED', { email: googleUser.email });
+ }
+ else {
+ logAuthEvent('USER_PENDING_APPROVAL', { email: googleUser.email });
+ }
+ }
+ else {
+ // Update last sign in
+ await databaseService_1.default.updateUserLastSignIn(googleUser.email);
+ logAuthEvent('USER_LOGIN', {
+ email: user.email,
+ name: user.name,
+ role: user.role,
+ approval_status: user.approval_status
+ });
+ }
+ // Check if user is approved
+ if (user.approval_status !== 'approved') {
+ logAuthEvent('USER_NOT_APPROVED', { email: user.email, status: user.approval_status });
+ return res.redirect(`${frontendUrl}?error=pending_approval&message=Your account is pending administrator approval`);
+ }
+ // Generate JWT token
+ const token = (0, simpleAuth_1.generateToken)(user);
+ logAuthEvent('JWT_TOKEN_GENERATED', {
+ user_id: user.id,
+ email: user.email,
+ role: user.role,
+ token_length: token.length
+ });
+ // Redirect to frontend with token
+ const callbackUrl = `${frontendUrl}/auth/callback?token=${token}`;
+ logAuthEvent('OAUTH_SUCCESS_REDIRECT', { callback_url: callbackUrl });
+ res.redirect(callbackUrl);
+ }
+ catch (error) {
+ logAuthEvent('OAUTH_CALLBACK_ERROR', {
+ error: error instanceof Error ? error.message : 'Unknown error',
+ stack: error instanceof Error ? error.stack : undefined,
+ ip: req.ip
+ });
+ res.redirect(`${frontendUrl}?error=oauth_failed&message=Authentication failed due to server error`);
+ }
+});
+// Exchange OAuth code for JWT token (alternative endpoint for frontend)
+router.post('/google/exchange', async (req, res) => {
+ const { code } = req.body;
+ if (!code) {
+ return res.status(400).json({ error: 'Authorization code is required' });
+ }
+ try {
+ // Exchange code for tokens
+ const tokens = await (0, simpleAuth_1.exchangeCodeForTokens)(code);
+ // Get user info
+ const googleUser = await (0, simpleAuth_1.getGoogleUserInfo)(tokens.access_token);
+ // Check if user exists or create new user
+ let user = await databaseService_1.default.getUserByEmail(googleUser.email);
+ if (!user) {
+ // Determine role - first user becomes admin
+ const userCount = await databaseService_1.default.getUserCount();
+ const role = userCount === 0 ? 'administrator' : 'coordinator';
+ user = await databaseService_1.default.createUser({
+ id: googleUser.id,
+ google_id: googleUser.id,
+ email: googleUser.email,
+ name: googleUser.name,
+ profile_picture_url: googleUser.picture,
+ role
+ });
+ }
+ else {
+ // Update last sign in
+ await databaseService_1.default.updateUserLastSignIn(googleUser.email);
+ console.log(`✅ User logged in: ${user.name} (${user.email})`);
+ }
+ // Generate JWT token
+ const token = (0, simpleAuth_1.generateToken)(user);
+ // Return token to frontend
+ res.json({
+ token,
+ user: {
+ id: user.id,
+ email: user.email,
+ name: user.name,
+ picture: user.profile_picture_url,
+ role: user.role
+ }
+ });
+ }
+ catch (error) {
+ console.error('Error in OAuth exchange:', error);
+ res.status(500).json({ error: 'Failed to exchange authorization code' });
+ }
+});
+// Get OAuth URL for frontend to redirect to
+router.get('/google/url', (req, res) => {
+ try {
+ const authUrl = (0, simpleAuth_1.getGoogleAuthUrl)();
+ res.json({ url: authUrl });
+ }
+ catch (error) {
+ console.error('Error getting Google OAuth URL:', error);
+ res.status(500).json({ error: 'OAuth not configured' });
+ }
+});
+// Logout
+router.post('/logout', (req, res) => {
+ // With JWT, logout is handled client-side by removing the token
+ res.json({ message: 'Logged out successfully' });
+});
+// Get auth status
+router.get('/status', (req, res) => {
+ const authHeader = req.headers.authorization;
+ if (!authHeader || !authHeader.startsWith('Bearer ')) {
+ return res.json({ authenticated: false });
+ }
+ const token = authHeader.substring(7);
+ const user = (0, simpleAuth_1.verifyToken)(token);
+ if (!user) {
+ return res.json({ authenticated: false });
+ }
+ res.json({
+ authenticated: true,
+ user: {
+ id: user.id,
+ email: user.email,
+ name: user.name,
+ picture: user.profile_picture_url,
+ role: user.role
+ }
+ });
+});
+// USER MANAGEMENT ENDPOINTS
+// List all users (admin only)
+router.get('/users', requireAuth, requireRole(['administrator']), async (req, res) => {
+ try {
+ const users = await databaseService_1.default.getAllUsers();
+ const userList = users.map(user => ({
+ id: user.id,
+ email: user.email,
+ name: user.name,
+ picture: user.profile_picture_url,
+ role: user.role,
+ created_at: user.created_at,
+ last_login: user.last_login,
+ provider: 'google'
+ }));
+ res.json(userList);
+ }
+ catch (error) {
+ console.error('Error fetching users:', error);
+ res.status(500).json({ error: 'Failed to fetch users' });
+ }
+});
+// Update user role (admin only)
+router.patch('/users/:email/role', requireAuth, requireRole(['administrator']), async (req, res) => {
+ const { email } = req.params;
+ const { role } = req.body;
+ if (!['administrator', 'coordinator', 'driver'].includes(role)) {
+ return res.status(400).json({ error: 'Invalid role' });
+ }
+ try {
+ const user = await databaseService_1.default.updateUserRole(email, role);
+ if (!user) {
+ return res.status(404).json({ error: 'User not found' });
+ }
+ res.json({
+ success: true,
+ user: {
+ id: user.id,
+ email: user.email,
+ name: user.name,
+ role: user.role
+ }
+ });
+ }
+ catch (error) {
+ console.error('Error updating user role:', error);
+ res.status(500).json({ error: 'Failed to update user role' });
+ }
+});
+// Delete user (admin only)
+router.delete('/users/:email', requireAuth, requireRole(['administrator']), async (req, res) => {
+ const { email } = req.params;
+ const currentUser = req.user;
+ // Prevent admin from deleting themselves
+ if (email === currentUser.email) {
+ return res.status(400).json({ error: 'Cannot delete your own account' });
+ }
+ try {
+ const deletedUser = await databaseService_1.default.deleteUser(email);
+ if (!deletedUser) {
+ return res.status(404).json({ error: 'User not found' });
+ }
+ res.json({ success: true, message: 'User deleted successfully' });
+ }
+ catch (error) {
+ console.error('Error deleting user:', error);
+ res.status(500).json({ error: 'Failed to delete user' });
+ }
+});
+// Get user by email (admin only)
+router.get('/users/:email', requireAuth, requireRole(['administrator']), async (req, res) => {
+ const { email } = req.params;
+ try {
+ const user = await databaseService_1.default.getUserByEmail(email);
+ if (!user) {
+ return res.status(404).json({ error: 'User not found' });
+ }
+ res.json({
+ id: user.id,
+ email: user.email,
+ name: user.name,
+ picture: user.profile_picture_url,
+ role: user.role,
+ created_at: user.created_at,
+ last_login: user.last_login,
+ provider: 'google',
+ approval_status: user.approval_status
+ });
+ }
+ catch (error) {
+ console.error('Error fetching user:', error);
+ res.status(500).json({ error: 'Failed to fetch user' });
+ }
+});
+// USER APPROVAL ENDPOINTS
+// Get pending users (admin only)
+router.get('/users/pending/list', requireAuth, requireRole(['administrator']), async (req, res) => {
+ try {
+ const pendingUsers = await databaseService_1.default.getPendingUsers();
+ const userList = pendingUsers.map(user => ({
+ id: user.id,
+ email: user.email,
+ name: user.name,
+ picture: user.profile_picture_url,
+ role: user.role,
+ created_at: user.created_at,
+ provider: 'google',
+ approval_status: user.approval_status
+ }));
+ res.json(userList);
+ }
+ catch (error) {
+ console.error('Error fetching pending users:', error);
+ res.status(500).json({ error: 'Failed to fetch pending users' });
+ }
+});
+// Approve or deny user (admin only)
+router.patch('/users/:email/approval', requireAuth, requireRole(['administrator']), async (req, res) => {
+ const { email } = req.params;
+ const { status } = req.body;
+ if (!['approved', 'denied'].includes(status)) {
+ return res.status(400).json({ error: 'Invalid approval status. Must be "approved" or "denied"' });
+ }
+ try {
+ const user = await databaseService_1.default.updateUserApprovalStatus(email, status);
+ if (!user) {
+ return res.status(404).json({ error: 'User not found' });
+ }
+ res.json({
+ success: true,
+ message: `User ${status} successfully`,
+ user: {
+ id: user.id,
+ email: user.email,
+ name: user.name,
+ role: user.role,
+ approval_status: user.approval_status
+ }
+ });
+ }
+ catch (error) {
+ console.error('Error updating user approval:', error);
+ res.status(500).json({ error: 'Failed to update user approval' });
+ }
+});
+exports.default = router;
+//# sourceMappingURL=simpleAuth.js.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/routes/simpleAuth.js.map b/backend-old-20260125/dist/routes/simpleAuth.js.map
new file mode 100644
index 0000000..83ddad3
--- /dev/null
+++ b/backend-old-20260125/dist/routes/simpleAuth.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"simpleAuth.js","sourceRoot":"","sources":["../../src/routes/simpleAuth.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/authService.d.ts b/backend-old-20260125/dist/services/authService.d.ts
new file mode 100644
index 0000000..d0189a5
--- /dev/null
+++ b/backend-old-20260125/dist/services/authService.d.ts
@@ -0,0 +1,29 @@
+import { Request, Response, NextFunction } from 'express';
+declare class AuthService {
+ private jwtSecret;
+ private jwtExpiry;
+ private googleClient;
+ constructor();
+ generateToken(user: any): string;
+ verifyGoogleToken(credential: string): Promise<{
+ user: any;
+ token: string;
+ }>;
+ verifyToken(token: string): any;
+ requireAuth: (req: Request & {
+ user?: any;
+ }, res: Response, next: NextFunction) => Promise> | undefined>;
+ requireRole: (roles: string[]) => (req: Request & {
+ user?: any;
+ }, res: Response, next: NextFunction) => Response> | undefined;
+ getGoogleAuthUrl(): string;
+ exchangeGoogleCode(code: string): Promise;
+ getGoogleUserInfo(accessToken: string): Promise;
+ handleGoogleAuth(code: string): Promise<{
+ user: any;
+ token: string;
+ }>;
+}
+declare const _default: AuthService;
+export default _default;
+//# sourceMappingURL=authService.d.ts.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/authService.d.ts.map b/backend-old-20260125/dist/services/authService.d.ts.map
new file mode 100644
index 0000000..83ae925
--- /dev/null
+++ b/backend-old-20260125/dist/services/authService.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"authService.d.ts","sourceRoot":"","sources":["../../src/services/authService.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAK1D,cAAM,WAAW;IACf,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAiB;IAClC,OAAO,CAAC,YAAY,CAAe;;IAoBnC,aAAa,CAAC,IAAI,EAAE,GAAG,GAAG,MAAM;IAM1B,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,GAAG,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAqClF,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG;IAS/B,WAAW,GAAU,KAAK,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,GAAG,CAAA;KAAE,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,6DAoBnF;IAGF,WAAW,GAAI,OAAO,MAAM,EAAE,MACpB,KAAK,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,GAAG,CAAA;KAAE,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,oDAWxE;IAGF,gBAAgB,IAAI,MAAM;IAiBpB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAoB9C,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAapD,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,GAAG,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CAyB5E;;AAED,wBAAiC"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/authService.js b/backend-old-20260125/dist/services/authService.js
new file mode 100644
index 0000000..c808d7f
--- /dev/null
+++ b/backend-old-20260125/dist/services/authService.js
@@ -0,0 +1,168 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const jwt = require('jsonwebtoken');
+const google_auth_library_1 = require("google-auth-library");
+const unifiedDataService_1 = __importDefault(require("./unifiedDataService"));
+// Simplified authentication service - removes excessive logging and complexity
+class AuthService {
+ constructor() {
+ this.jwtExpiry = '24h';
+ // Middleware to check authentication
+ this.requireAuth = async (req, res, next) => {
+ const token = req.headers.authorization?.replace('Bearer ', '');
+ if (!token) {
+ return res.status(401).json({ error: 'Authentication required' });
+ }
+ const decoded = this.verifyToken(token);
+ if (!decoded) {
+ return res.status(401).json({ error: 'Invalid or expired token' });
+ }
+ // Get fresh user data
+ const user = await unifiedDataService_1.default.getUserById(decoded.id);
+ if (!user) {
+ return res.status(401).json({ error: 'User not found' });
+ }
+ req.user = user;
+ next();
+ };
+ // Middleware to check role
+ this.requireRole = (roles) => {
+ return (req, res, next) => {
+ if (!req.user) {
+ return res.status(401).json({ error: 'Authentication required' });
+ }
+ if (!roles.includes(req.user.role)) {
+ return res.status(403).json({ error: 'Insufficient permissions' });
+ }
+ next();
+ };
+ };
+ // Auto-generate a secure JWT secret if not provided
+ if (process.env.JWT_SECRET) {
+ this.jwtSecret = process.env.JWT_SECRET;
+ console.log('Using JWT_SECRET from environment');
+ }
+ else {
+ // Generate a cryptographically secure random secret
+ const crypto = require('crypto');
+ this.jwtSecret = crypto.randomBytes(64).toString('hex');
+ console.log('Generated new JWT_SECRET (this will change on restart)');
+ console.log('To persist sessions across restarts, set JWT_SECRET in .env');
+ }
+ // Initialize Google OAuth client
+ this.googleClient = new google_auth_library_1.OAuth2Client(process.env.GOOGLE_CLIENT_ID);
+ }
+ // Generate JWT token
+ generateToken(user) {
+ const payload = { id: user.id, email: user.email, role: user.role };
+ return jwt.sign(payload, this.jwtSecret, { expiresIn: this.jwtExpiry });
+ }
+ // Verify Google ID token from frontend
+ async verifyGoogleToken(credential) {
+ try {
+ // Verify the token with Google
+ const ticket = await this.googleClient.verifyIdToken({
+ idToken: credential,
+ audience: process.env.GOOGLE_CLIENT_ID,
+ });
+ const payload = ticket.getPayload();
+ if (!payload || !payload.email) {
+ throw new Error('Invalid token payload');
+ }
+ // Find or create user
+ let user = await unifiedDataService_1.default.getUserByEmail(payload.email);
+ if (!user) {
+ // Auto-create user with coordinator role
+ user = await unifiedDataService_1.default.createUser({
+ email: payload.email,
+ name: payload.name || payload.email,
+ role: 'coordinator',
+ googleId: payload.sub
+ });
+ }
+ // Generate our JWT
+ const token = this.generateToken(user);
+ return { user, token };
+ }
+ catch (error) {
+ console.error('Token verification error:', error);
+ throw new Error('Failed to verify Google token');
+ }
+ }
+ // Verify JWT token
+ verifyToken(token) {
+ try {
+ return jwt.verify(token, this.jwtSecret);
+ }
+ catch (error) {
+ return null;
+ }
+ }
+ // Google OAuth helpers
+ getGoogleAuthUrl() {
+ if (!process.env.GOOGLE_CLIENT_ID || !process.env.GOOGLE_REDIRECT_URI) {
+ throw new Error('Google OAuth not configured. Please set GOOGLE_CLIENT_ID and GOOGLE_REDIRECT_URI in .env file');
+ }
+ const params = new URLSearchParams({
+ client_id: process.env.GOOGLE_CLIENT_ID,
+ redirect_uri: process.env.GOOGLE_REDIRECT_URI,
+ response_type: 'code',
+ scope: 'email profile',
+ access_type: 'offline',
+ prompt: 'consent'
+ });
+ return `https://accounts.google.com/o/oauth2/v2/auth?${params}`;
+ }
+ async exchangeGoogleCode(code) {
+ const response = await fetch('https://oauth2.googleapis.com/token', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({
+ code,
+ client_id: process.env.GOOGLE_CLIENT_ID,
+ client_secret: process.env.GOOGLE_CLIENT_SECRET,
+ redirect_uri: process.env.GOOGLE_REDIRECT_URI,
+ grant_type: 'authorization_code'
+ })
+ });
+ if (!response.ok) {
+ throw new Error('Failed to exchange authorization code');
+ }
+ return response.json();
+ }
+ async getGoogleUserInfo(accessToken) {
+ const response = await fetch('https://www.googleapis.com/oauth2/v2/userinfo', {
+ headers: { Authorization: `Bearer ${accessToken}` }
+ });
+ if (!response.ok) {
+ throw new Error('Failed to get user info');
+ }
+ return response.json();
+ }
+ // Simplified login/signup
+ async handleGoogleAuth(code) {
+ // Exchange code for tokens
+ const tokens = await this.exchangeGoogleCode(code);
+ // Get user info
+ const googleUser = await this.getGoogleUserInfo(tokens.access_token);
+ // Find or create user
+ let user = await unifiedDataService_1.default.getUserByEmail(googleUser.email);
+ if (!user) {
+ // Auto-create user with coordinator role
+ user = await unifiedDataService_1.default.createUser({
+ email: googleUser.email,
+ name: googleUser.name,
+ role: 'coordinator',
+ googleId: googleUser.id
+ });
+ }
+ // Generate JWT
+ const token = this.generateToken(user);
+ return { user, token };
+ }
+}
+exports.default = new AuthService();
+//# sourceMappingURL=authService.js.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/authService.js.map b/backend-old-20260125/dist/services/authService.js.map
new file mode 100644
index 0000000..cd31567
--- /dev/null
+++ b/backend-old-20260125/dist/services/authService.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"authService.js","sourceRoot":"","sources":["../../src/services/authService.ts"],"names":[],"mappings":";;;;;AAAA,MAAM,GAAG,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;AAEpC,6DAAmD;AACnD,8EAA+C;AAE/C,+EAA+E;AAC/E,MAAM,WAAW;IAKf;QAHQ,cAAS,GAAW,KAAK,CAAC;QAwElC,qCAAqC;QACrC,gBAAW,GAAG,KAAK,EAAE,GAA6B,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;YACvF,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,EAAE,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;YAEhE,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,yBAAyB,EAAE,CAAC,CAAC;YACpE,CAAC;YAED,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YACxC,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,0BAA0B,EAAE,CAAC,CAAC;YACrE,CAAC;YAED,sBAAsB;YACtB,MAAM,IAAI,GAAG,MAAM,4BAAW,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YACvD,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC,CAAC;YAC3D,CAAC;YAED,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;YAChB,IAAI,EAAE,CAAC;QACT,CAAC,CAAC;QAEF,2BAA2B;QAC3B,gBAAW,GAAG,CAAC,KAAe,EAAE,EAAE;YAChC,OAAO,CAAC,GAA6B,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;gBAC1E,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;oBACd,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,yBAAyB,EAAE,CAAC,CAAC;gBACpE,CAAC;gBAED,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;oBACnC,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,0BAA0B,EAAE,CAAC,CAAC;gBACrE,CAAC;gBAED,IAAI,EAAE,CAAC;YACT,CAAC,CAAC;QACJ,CAAC,CAAC;QAxGA,oDAAoD;QACpD,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC;YAC3B,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;YACxC,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;QACnD,CAAC;aAAM,CAAC;YACN,oDAAoD;YACpD,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;YACjC,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YACxD,OAAO,CAAC,GAAG,CAAC,wDAAwD,CAAC,CAAC;YACtE,OAAO,CAAC,GAAG,CAAC,6DAA6D,CAAC,CAAC;QAC7E,CAAC;QAED,iCAAiC;QACjC,IAAI,CAAC,YAAY,GAAG,IAAI,kCAAY,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IACrE,CAAC;IAED,qBAAqB;IACrB,aAAa,CAAC,IAAS;QACrB,MAAM,OAAO,GAAG,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;QACpE,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAW,CAAC;IACpF,CAAC;IAED,uCAAuC;IACvC,KAAK,CAAC,iBAAiB,CAAC,UAAkB;QACxC,IAAI,CAAC;YACH,+BAA+B;YAC/B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC;gBACnD,OAAO,EAAE,UAAU;gBACnB,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB;aACvC,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;YACpC,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;gBAC/B,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;YAC3C,CAAC;YAED,sBAAsB;YACtB,IAAI,IAAI,GAAG,MAAM,4BAAW,CAAC,cAAc,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAE3D,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,yCAAyC;gBACzC,IAAI,GAAG,MAAM,4BAAW,CAAC,UAAU,CAAC;oBAClC,KAAK,EAAE,OAAO,CAAC,KAAK;oBACpB,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,KAAK;oBACnC,IAAI,EAAE,aAAa;oBACnB,QAAQ,EAAE,OAAO,CAAC,GAAG;iBACtB,CAAC,CAAC;YACL,CAAC;YAED,mBAAmB;YACnB,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;YAEvC,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QACzB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAC;YAClD,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IAED,mBAAmB;IACnB,WAAW,CAAC,KAAa;QACvB,IAAI,CAAC;YACH,OAAO,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QAC3C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAwCD,uBAAuB;IACvB,gBAAgB;QACd,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,CAAC;YACtE,MAAM,IAAI,KAAK,CAAC,+FAA+F,CAAC,CAAC;QACnH,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;YACjC,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB;YACvC,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB;YAC7C,aAAa,EAAE,MAAM;YACrB,KAAK,EAAE,eAAe;YACtB,WAAW,EAAE,SAAS;YACtB,MAAM,EAAE,SAAS;SAClB,CAAC,CAAC;QAEH,OAAO,gDAAgD,MAAM,EAAE,CAAC;IAClE,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,IAAY;QACnC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,qCAAqC,EAAE;YAClE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,IAAI;gBACJ,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB;gBACvC,aAAa,EAAE,OAAO,CAAC,GAAG,CAAC,oBAAoB;gBAC/C,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB;gBAC7C,UAAU,EAAE,oBAAoB;aACjC,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAC3D,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,WAAmB;QACzC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,+CAA+C,EAAE;YAC5E,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,WAAW,EAAE,EAAE;SACpD,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC7C,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;IACzB,CAAC;IAED,0BAA0B;IAC1B,KAAK,CAAC,gBAAgB,CAAC,IAAY;QACjC,2BAA2B;QAC3B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;QAEnD,gBAAgB;QAChB,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAErE,sBAAsB;QACtB,IAAI,IAAI,GAAG,MAAM,4BAAW,CAAC,cAAc,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAE9D,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,yCAAyC;YACzC,IAAI,GAAG,MAAM,4BAAW,CAAC,UAAU,CAAC;gBAClC,KAAK,EAAE,UAAU,CAAC,KAAK;gBACvB,IAAI,EAAE,UAAU,CAAC,IAAI;gBACrB,IAAI,EAAE,aAAa;gBACnB,QAAQ,EAAE,UAAU,CAAC,EAAE;aACxB,CAAC,CAAC;QACL,CAAC;QAED,eAAe;QACf,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QAEvC,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IACzB,CAAC;CACF;AAED,kBAAe,IAAI,WAAW,EAAE,CAAC"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/dataService.d.ts b/backend-old-20260125/dist/services/dataService.d.ts
new file mode 100644
index 0000000..88f8115
--- /dev/null
+++ b/backend-old-20260125/dist/services/dataService.d.ts
@@ -0,0 +1,39 @@
+declare class DataService {
+ private dataDir;
+ private dataFile;
+ private data;
+ constructor();
+ private loadData;
+ private saveData;
+ getVips(): any[];
+ addVip(vip: any): any;
+ updateVip(id: string, updatedVip: any): any | null;
+ deleteVip(id: string): any | null;
+ getDrivers(): any[];
+ addDriver(driver: any): any;
+ updateDriver(id: string, updatedDriver: any): any | null;
+ deleteDriver(id: string): any | null;
+ getSchedule(vipId: string): any[];
+ addScheduleEvent(vipId: string, event: any): any;
+ updateScheduleEvent(vipId: string, eventId: string, updatedEvent: any): any | null;
+ deleteScheduleEvent(vipId: string, eventId: string): any | null;
+ getAllSchedules(): {
+ [vipId: string]: any[];
+ };
+ getAdminSettings(): any;
+ updateAdminSettings(settings: any): void;
+ createBackup(): string;
+ getUsers(): any[];
+ getUserByEmail(email: string): any | null;
+ getUserById(id: string): any | null;
+ addUser(user: any): any;
+ updateUser(email: string, updatedUser: any): any | null;
+ updateUserRole(email: string, role: string): any | null;
+ updateUserLastSignIn(email: string): any | null;
+ deleteUser(email: string): any | null;
+ getUserCount(): number;
+ getDataStats(): any;
+}
+declare const _default: DataService;
+export default _default;
+//# sourceMappingURL=dataService.d.ts.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/dataService.d.ts.map b/backend-old-20260125/dist/services/dataService.d.ts.map
new file mode 100644
index 0000000..403a5d0
--- /dev/null
+++ b/backend-old-20260125/dist/services/dataService.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"dataService.d.ts","sourceRoot":"","sources":["../../src/services/dataService.ts"],"names":[],"mappings":"AAWA,cAAM,WAAW;IACf,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,IAAI,CAAY;;IAcxB,OAAO,CAAC,QAAQ;IA6ChB,OAAO,CAAC,QAAQ;IAWhB,OAAO,IAAI,GAAG,EAAE;IAIhB,MAAM,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG;IAMrB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,GAAG,GAAG,GAAG,IAAI;IAUlD,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI;IAajC,UAAU,IAAI,GAAG,EAAE;IAInB,SAAS,CAAC,MAAM,EAAE,GAAG,GAAG,GAAG;IAM3B,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,GAAG,GAAG,GAAG,GAAG,IAAI;IAUxD,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI;IAWpC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,EAAE;IAIjC,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,GAAG;IAShD,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,GAAG,GAAG,GAAG,IAAI;IAclF,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI;IAc/D,eAAe,IAAI;QAAE,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,EAAE,CAAA;KAAE;IAK7C,gBAAgB,IAAI,GAAG;IAIvB,mBAAmB,CAAC,QAAQ,EAAE,GAAG,GAAG,IAAI;IAMxC,YAAY,IAAI,MAAM;IAetB,QAAQ,IAAI,GAAG,EAAE;IAIjB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI;IAIzC,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI;IAInC,OAAO,CAAC,IAAI,EAAE,GAAG,GAAG,GAAG;IAcvB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,GAAG,GAAG,GAAG,IAAI;IAWvD,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI;IAWvD,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI;IAU/C,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI;IAWrC,YAAY,IAAI,MAAM;IAItB,YAAY,IAAI,GAAG;CAWpB;;AAED,wBAAiC"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/dataService.js b/backend-old-20260125/dist/services/dataService.js
new file mode 100644
index 0000000..b922ba3
--- /dev/null
+++ b/backend-old-20260125/dist/services/dataService.js
@@ -0,0 +1,264 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const fs_1 = __importDefault(require("fs"));
+const path_1 = __importDefault(require("path"));
+class DataService {
+ constructor() {
+ this.dataDir = path_1.default.join(process.cwd(), 'data');
+ this.dataFile = path_1.default.join(this.dataDir, 'vip-coordinator.json');
+ // Ensure data directory exists
+ if (!fs_1.default.existsSync(this.dataDir)) {
+ fs_1.default.mkdirSync(this.dataDir, { recursive: true });
+ }
+ this.data = this.loadData();
+ }
+ loadData() {
+ try {
+ if (fs_1.default.existsSync(this.dataFile)) {
+ const fileContent = fs_1.default.readFileSync(this.dataFile, 'utf8');
+ const loadedData = JSON.parse(fileContent);
+ console.log(`✅ Loaded data from ${this.dataFile}`);
+ console.log(` - VIPs: ${loadedData.vips?.length || 0}`);
+ console.log(` - Drivers: ${loadedData.drivers?.length || 0}`);
+ console.log(` - Users: ${loadedData.users?.length || 0}`);
+ console.log(` - Schedules: ${Object.keys(loadedData.schedules || {}).length} VIPs with schedules`);
+ // Ensure users array exists for backward compatibility
+ if (!loadedData.users) {
+ loadedData.users = [];
+ }
+ return loadedData;
+ }
+ }
+ catch (error) {
+ console.error('Error loading data file:', error);
+ }
+ // Return default empty data structure
+ console.log('📝 Starting with empty data store');
+ return {
+ vips: [],
+ drivers: [],
+ schedules: {},
+ users: [],
+ adminSettings: {
+ apiKeys: {
+ aviationStackKey: process.env.AVIATIONSTACK_API_KEY || '',
+ googleMapsKey: '',
+ twilioKey: ''
+ },
+ systemSettings: {
+ defaultPickupLocation: '',
+ defaultDropoffLocation: '',
+ timeZone: 'America/New_York',
+ notificationsEnabled: false
+ }
+ }
+ };
+ }
+ saveData() {
+ try {
+ const dataToSave = JSON.stringify(this.data, null, 2);
+ fs_1.default.writeFileSync(this.dataFile, dataToSave, 'utf8');
+ console.log(`💾 Data saved to ${this.dataFile}`);
+ }
+ catch (error) {
+ console.error('Error saving data file:', error);
+ }
+ }
+ // VIP operations
+ getVips() {
+ return this.data.vips;
+ }
+ addVip(vip) {
+ this.data.vips.push(vip);
+ this.saveData();
+ return vip;
+ }
+ updateVip(id, updatedVip) {
+ const index = this.data.vips.findIndex(vip => vip.id === id);
+ if (index !== -1) {
+ this.data.vips[index] = updatedVip;
+ this.saveData();
+ return this.data.vips[index];
+ }
+ return null;
+ }
+ deleteVip(id) {
+ const index = this.data.vips.findIndex(vip => vip.id === id);
+ if (index !== -1) {
+ const deletedVip = this.data.vips.splice(index, 1)[0];
+ // Also delete the VIP's schedule
+ delete this.data.schedules[id];
+ this.saveData();
+ return deletedVip;
+ }
+ return null;
+ }
+ // Driver operations
+ getDrivers() {
+ return this.data.drivers;
+ }
+ addDriver(driver) {
+ this.data.drivers.push(driver);
+ this.saveData();
+ return driver;
+ }
+ updateDriver(id, updatedDriver) {
+ const index = this.data.drivers.findIndex(driver => driver.id === id);
+ if (index !== -1) {
+ this.data.drivers[index] = updatedDriver;
+ this.saveData();
+ return this.data.drivers[index];
+ }
+ return null;
+ }
+ deleteDriver(id) {
+ const index = this.data.drivers.findIndex(driver => driver.id === id);
+ if (index !== -1) {
+ const deletedDriver = this.data.drivers.splice(index, 1)[0];
+ this.saveData();
+ return deletedDriver;
+ }
+ return null;
+ }
+ // Schedule operations
+ getSchedule(vipId) {
+ return this.data.schedules[vipId] || [];
+ }
+ addScheduleEvent(vipId, event) {
+ if (!this.data.schedules[vipId]) {
+ this.data.schedules[vipId] = [];
+ }
+ this.data.schedules[vipId].push(event);
+ this.saveData();
+ return event;
+ }
+ updateScheduleEvent(vipId, eventId, updatedEvent) {
+ if (!this.data.schedules[vipId]) {
+ return null;
+ }
+ const index = this.data.schedules[vipId].findIndex(event => event.id === eventId);
+ if (index !== -1) {
+ this.data.schedules[vipId][index] = updatedEvent;
+ this.saveData();
+ return this.data.schedules[vipId][index];
+ }
+ return null;
+ }
+ deleteScheduleEvent(vipId, eventId) {
+ if (!this.data.schedules[vipId]) {
+ return null;
+ }
+ const index = this.data.schedules[vipId].findIndex(event => event.id === eventId);
+ if (index !== -1) {
+ const deletedEvent = this.data.schedules[vipId].splice(index, 1)[0];
+ this.saveData();
+ return deletedEvent;
+ }
+ return null;
+ }
+ getAllSchedules() {
+ return this.data.schedules;
+ }
+ // Admin settings operations
+ getAdminSettings() {
+ return this.data.adminSettings;
+ }
+ updateAdminSettings(settings) {
+ this.data.adminSettings = { ...this.data.adminSettings, ...settings };
+ this.saveData();
+ }
+ // Backup and restore operations
+ createBackup() {
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
+ const backupFile = path_1.default.join(this.dataDir, `backup-${timestamp}.json`);
+ try {
+ fs_1.default.copyFileSync(this.dataFile, backupFile);
+ console.log(`📦 Backup created: ${backupFile}`);
+ return backupFile;
+ }
+ catch (error) {
+ console.error('Error creating backup:', error);
+ throw error;
+ }
+ }
+ // User operations
+ getUsers() {
+ return this.data.users;
+ }
+ getUserByEmail(email) {
+ return this.data.users.find(user => user.email === email) || null;
+ }
+ getUserById(id) {
+ return this.data.users.find(user => user.id === id) || null;
+ }
+ addUser(user) {
+ // Add timestamps
+ const userWithTimestamps = {
+ ...user,
+ created_at: new Date().toISOString(),
+ last_sign_in_at: new Date().toISOString()
+ };
+ this.data.users.push(userWithTimestamps);
+ this.saveData();
+ console.log(`👤 Added user: ${user.name} (${user.email}) as ${user.role}`);
+ return userWithTimestamps;
+ }
+ updateUser(email, updatedUser) {
+ const index = this.data.users.findIndex(user => user.email === email);
+ if (index !== -1) {
+ this.data.users[index] = { ...this.data.users[index], ...updatedUser };
+ this.saveData();
+ console.log(`👤 Updated user: ${this.data.users[index].name} (${email})`);
+ return this.data.users[index];
+ }
+ return null;
+ }
+ updateUserRole(email, role) {
+ const index = this.data.users.findIndex(user => user.email === email);
+ if (index !== -1) {
+ this.data.users[index].role = role;
+ this.saveData();
+ console.log(`👤 Updated user role: ${this.data.users[index].name} (${email}) -> ${role}`);
+ return this.data.users[index];
+ }
+ return null;
+ }
+ updateUserLastSignIn(email) {
+ const index = this.data.users.findIndex(user => user.email === email);
+ if (index !== -1) {
+ this.data.users[index].last_sign_in_at = new Date().toISOString();
+ this.saveData();
+ return this.data.users[index];
+ }
+ return null;
+ }
+ deleteUser(email) {
+ const index = this.data.users.findIndex(user => user.email === email);
+ if (index !== -1) {
+ const deletedUser = this.data.users.splice(index, 1)[0];
+ this.saveData();
+ console.log(`👤 Deleted user: ${deletedUser.name} (${email})`);
+ return deletedUser;
+ }
+ return null;
+ }
+ getUserCount() {
+ return this.data.users.length;
+ }
+ getDataStats() {
+ return {
+ vips: this.data.vips.length,
+ drivers: this.data.drivers.length,
+ users: this.data.users.length,
+ scheduledEvents: Object.values(this.data.schedules).reduce((total, events) => total + events.length, 0),
+ vipsWithSchedules: Object.keys(this.data.schedules).length,
+ dataFile: this.dataFile,
+ lastModified: fs_1.default.existsSync(this.dataFile) ? fs_1.default.statSync(this.dataFile).mtime : null
+ };
+ }
+}
+exports.default = new DataService();
+//# sourceMappingURL=dataService.js.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/dataService.js.map b/backend-old-20260125/dist/services/dataService.js.map
new file mode 100644
index 0000000..ceac118
--- /dev/null
+++ b/backend-old-20260125/dist/services/dataService.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"dataService.js","sourceRoot":"","sources":["../../src/services/dataService.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/databaseService.d.ts b/backend-old-20260125/dist/services/databaseService.d.ts
new file mode 100644
index 0000000..e18e450
--- /dev/null
+++ b/backend-old-20260125/dist/services/databaseService.d.ts
@@ -0,0 +1,56 @@
+import { PoolClient } from 'pg';
+declare class EnhancedDatabaseService {
+ private backupService;
+ constructor();
+ query(text: string, params?: any[]): Promise;
+ getClient(): Promise;
+ close(): Promise;
+ initializeTables(): Promise;
+ createUser(user: any): Promise;
+ getUserByEmail(email: string): Promise;
+ getUserById(id: string): Promise;
+ updateUserRole(email: string, role: string): Promise;
+ updateUserLastSignIn(email: string): Promise;
+ getUserCount(): Promise;
+ updateUserApprovalStatus(email: string, status: 'pending' | 'approved' | 'denied'): Promise;
+ getApprovedUserCount(): Promise;
+ getAllUsers(): Promise;
+ deleteUser(email: string): Promise;
+ getPendingUsers(): Promise;
+ completeUserOnboarding(email: string, onboardingData: any): Promise;
+ approveUser(userEmail: string, approvedBy: string, newRole?: string): Promise;
+ rejectUser(userEmail: string, rejectedBy: string, reason?: string): Promise;
+ deactivateUser(userEmail: string, deactivatedBy: string): Promise;
+ reactivateUser(userEmail: string, reactivatedBy: string): Promise;
+ createAuditLog(action: string, userEmail: string, performedBy: string, details: any): Promise;
+ getUserAuditLog(userEmail: string): Promise;
+ getUsersWithFilters(filters: {
+ status?: string;
+ role?: string;
+ search?: string;
+ }): Promise;
+ getActiveUserCount(): Promise;
+ isFirstUser(): Promise;
+ createVip(vip: any): Promise;
+ getVipById(id: string): Promise;
+ getAllVips(): Promise;
+ updateVip(id: string, vip: any): Promise;
+ deleteVip(id: string): Promise;
+ getVipsByDepartment(department: string): Promise;
+ createDriver(driver: any): Promise;
+ getDriverById(id: string): Promise;
+ getAllDrivers(): Promise;
+ updateDriver(id: string, driver: any): Promise;
+ deleteDriver(id: string): Promise;
+ getDriversByDepartment(department: string): Promise;
+ updateDriverLocation(id: string, location: any): Promise;
+ createScheduleEvent(vipId: string, event: any): Promise;
+ getScheduleByVipId(vipId: string): Promise;
+ updateScheduleEvent(vipId: string, eventId: string, event: any): Promise;
+ deleteScheduleEvent(vipId: string, eventId: string): Promise;
+ getAllScheduleEvents(): Promise;
+ getScheduleEventsByDateRange(startDate: Date, endDate: Date): Promise;
+}
+declare const databaseService: EnhancedDatabaseService;
+export default databaseService;
+//# sourceMappingURL=databaseService.d.ts.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/databaseService.d.ts.map b/backend-old-20260125/dist/services/databaseService.d.ts.map
new file mode 100644
index 0000000..4e295e7
--- /dev/null
+++ b/backend-old-20260125/dist/services/databaseService.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"databaseService.d.ts","sourceRoot":"","sources":["../../src/services/databaseService.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/databaseService.js b/backend-old-20260125/dist/services/databaseService.js
new file mode 100644
index 0000000..fcc3e05
--- /dev/null
+++ b/backend-old-20260125/dist/services/databaseService.js
@@ -0,0 +1,265 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+// Import the existing backup service
+const databaseService_1 = __importDefault(require("./backup-services/databaseService"));
+// Extend the backup service with new user management methods
+class EnhancedDatabaseService {
+ constructor() {
+ this.backupService = databaseService_1.default;
+ }
+ // Delegate all existing methods to backup service
+ async query(text, params) {
+ return this.backupService.query(text, params);
+ }
+ async getClient() {
+ return this.backupService.getClient();
+ }
+ async close() {
+ return this.backupService.close();
+ }
+ async initializeTables() {
+ return this.backupService.initializeTables();
+ }
+ // User methods from backup service
+ async createUser(user) {
+ return this.backupService.createUser(user);
+ }
+ async getUserByEmail(email) {
+ return this.backupService.getUserByEmail(email);
+ }
+ async getUserById(id) {
+ return this.backupService.getUserById(id);
+ }
+ async updateUserRole(email, role) {
+ return this.backupService.updateUserRole(email, role);
+ }
+ async updateUserLastSignIn(email) {
+ return this.backupService.updateUserLastSignIn(email);
+ }
+ async getUserCount() {
+ return this.backupService.getUserCount();
+ }
+ async updateUserApprovalStatus(email, status) {
+ return this.backupService.updateUserApprovalStatus(email, status);
+ }
+ async getApprovedUserCount() {
+ return this.backupService.getApprovedUserCount();
+ }
+ async getAllUsers() {
+ return this.backupService.getAllUsers();
+ }
+ async deleteUser(email) {
+ return this.backupService.deleteUser(email);
+ }
+ async getPendingUsers() {
+ return this.backupService.getPendingUsers();
+ }
+ // NEW: Enhanced user management methods
+ async completeUserOnboarding(email, onboardingData) {
+ const query = `
+ UPDATE users
+ SET phone = $1,
+ organization = $2,
+ onboarding_data = $3,
+ updated_at = CURRENT_TIMESTAMP
+ WHERE email = $4
+ RETURNING *
+ `;
+ const result = await this.query(query, [
+ onboardingData.phone,
+ onboardingData.organization,
+ JSON.stringify(onboardingData),
+ email
+ ]);
+ return result.rows[0] || null;
+ }
+ async approveUser(userEmail, approvedBy, newRole) {
+ const query = `
+ UPDATE users
+ SET status = 'active',
+ approval_status = 'approved',
+ approved_by = $1,
+ approved_at = CURRENT_TIMESTAMP,
+ role = COALESCE($2, role),
+ updated_at = CURRENT_TIMESTAMP
+ WHERE email = $3
+ RETURNING *
+ `;
+ const result = await this.query(query, [approvedBy, newRole, userEmail]);
+ // Log audit
+ if (result.rows[0]) {
+ await this.createAuditLog('user_approved', userEmail, approvedBy, { newRole });
+ }
+ return result.rows[0] || null;
+ }
+ async rejectUser(userEmail, rejectedBy, reason) {
+ const query = `
+ UPDATE users
+ SET status = 'deactivated',
+ approval_status = 'denied',
+ rejected_by = $1,
+ rejected_at = CURRENT_TIMESTAMP,
+ updated_at = CURRENT_TIMESTAMP
+ WHERE email = $2
+ RETURNING *
+ `;
+ const result = await this.query(query, [rejectedBy, userEmail]);
+ // Log audit
+ if (result.rows[0]) {
+ await this.createAuditLog('user_rejected', userEmail, rejectedBy, { reason });
+ }
+ return result.rows[0] || null;
+ }
+ async deactivateUser(userEmail, deactivatedBy) {
+ const query = `
+ UPDATE users
+ SET status = 'deactivated',
+ deactivated_by = $1,
+ deactivated_at = CURRENT_TIMESTAMP,
+ updated_at = CURRENT_TIMESTAMP
+ WHERE email = $2
+ RETURNING *
+ `;
+ const result = await this.query(query, [deactivatedBy, userEmail]);
+ // Log audit
+ if (result.rows[0]) {
+ await this.createAuditLog('user_deactivated', userEmail, deactivatedBy, {});
+ }
+ return result.rows[0] || null;
+ }
+ async reactivateUser(userEmail, reactivatedBy) {
+ const query = `
+ UPDATE users
+ SET status = 'active',
+ deactivated_by = NULL,
+ deactivated_at = NULL,
+ updated_at = CURRENT_TIMESTAMP
+ WHERE email = $1
+ RETURNING *
+ `;
+ const result = await this.query(query, [userEmail]);
+ // Log audit
+ if (result.rows[0]) {
+ await this.createAuditLog('user_reactivated', userEmail, reactivatedBy, {});
+ }
+ return result.rows[0] || null;
+ }
+ async createAuditLog(action, userEmail, performedBy, details) {
+ const query = `
+ INSERT INTO user_audit_log (action, user_email, performed_by, action_details)
+ VALUES ($1, $2, $3, $4)
+ `;
+ await this.query(query, [action, userEmail, performedBy, JSON.stringify(details)]);
+ }
+ async getUserAuditLog(userEmail) {
+ const query = `
+ SELECT * FROM user_audit_log
+ WHERE user_email = $1
+ ORDER BY created_at DESC
+ `;
+ const result = await this.query(query, [userEmail]);
+ return result.rows;
+ }
+ async getUsersWithFilters(filters) {
+ let query = 'SELECT * FROM users WHERE 1=1';
+ const params = [];
+ let paramIndex = 1;
+ if (filters.status) {
+ query += ` AND status = $${paramIndex}`;
+ params.push(filters.status);
+ paramIndex++;
+ }
+ if (filters.role) {
+ query += ` AND role = $${paramIndex}`;
+ params.push(filters.role);
+ paramIndex++;
+ }
+ if (filters.search) {
+ query += ` AND (LOWER(name) LIKE LOWER($${paramIndex}) OR LOWER(email) LIKE LOWER($${paramIndex}) OR LOWER(organization) LIKE LOWER($${paramIndex}))`;
+ params.push(`%${filters.search}%`);
+ paramIndex++;
+ }
+ query += ' ORDER BY created_at DESC';
+ const result = await this.query(query, params);
+ return result.rows;
+ }
+ // Fix for first user admin issue
+ async getActiveUserCount() {
+ const query = "SELECT COUNT(*) as count FROM users WHERE status = 'active'";
+ const result = await this.query(query);
+ return parseInt(result.rows[0].count);
+ }
+ async isFirstUser() {
+ // Check if there are any active or approved users
+ const query = "SELECT COUNT(*) as count FROM users WHERE status = 'active' OR approval_status = 'approved'";
+ const result = await this.query(query);
+ return parseInt(result.rows[0].count) === 0;
+ }
+ // VIP methods from backup service
+ async createVip(vip) {
+ return this.backupService.createVip(vip);
+ }
+ async getVipById(id) {
+ return this.backupService.getVipById(id);
+ }
+ async getAllVips() {
+ return this.backupService.getAllVips();
+ }
+ async updateVip(id, vip) {
+ return this.backupService.updateVip(id, vip);
+ }
+ async deleteVip(id) {
+ return this.backupService.deleteVip(id);
+ }
+ async getVipsByDepartment(department) {
+ return this.backupService.getVipsByDepartment(department);
+ }
+ // Driver methods from backup service
+ async createDriver(driver) {
+ return this.backupService.createDriver(driver);
+ }
+ async getDriverById(id) {
+ return this.backupService.getDriverById(id);
+ }
+ async getAllDrivers() {
+ return this.backupService.getAllDrivers();
+ }
+ async updateDriver(id, driver) {
+ return this.backupService.updateDriver(id, driver);
+ }
+ async deleteDriver(id) {
+ return this.backupService.deleteDriver(id);
+ }
+ async getDriversByDepartment(department) {
+ return this.backupService.getDriversByDepartment(department);
+ }
+ async updateDriverLocation(id, location) {
+ return this.backupService.updateDriverLocation(id, location);
+ }
+ // Schedule methods from backup service
+ async createScheduleEvent(vipId, event) {
+ return this.backupService.createScheduleEvent(vipId, event);
+ }
+ async getScheduleByVipId(vipId) {
+ return this.backupService.getScheduleByVipId(vipId);
+ }
+ async updateScheduleEvent(vipId, eventId, event) {
+ return this.backupService.updateScheduleEvent(vipId, eventId, event);
+ }
+ async deleteScheduleEvent(vipId, eventId) {
+ return this.backupService.deleteScheduleEvent(vipId, eventId);
+ }
+ async getAllScheduleEvents() {
+ return this.backupService.getAllScheduleEvents();
+ }
+ async getScheduleEventsByDateRange(startDate, endDate) {
+ return this.backupService.getScheduleEventsByDateRange(startDate, endDate);
+ }
+}
+// Export singleton instance
+const databaseService = new EnhancedDatabaseService();
+exports.default = databaseService;
+//# sourceMappingURL=databaseService.js.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/databaseService.js.map b/backend-old-20260125/dist/services/databaseService.js.map
new file mode 100644
index 0000000..2e4ce58
--- /dev/null
+++ b/backend-old-20260125/dist/services/databaseService.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"databaseService.js","sourceRoot":"","sources":["../../src/services/databaseService.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/driverConflictService.d.ts b/backend-old-20260125/dist/services/driverConflictService.d.ts
new file mode 100644
index 0000000..af66dd3
--- /dev/null
+++ b/backend-old-20260125/dist/services/driverConflictService.d.ts
@@ -0,0 +1,49 @@
+interface ScheduleEvent {
+ id: string;
+ title: string;
+ location: string;
+ startTime: string;
+ endTime: string;
+ assignedDriverId?: string;
+ vipId: string;
+ vipName: string;
+}
+interface ConflictInfo {
+ type: 'overlap' | 'tight_turnaround' | 'back_to_back';
+ severity: 'low' | 'medium' | 'high';
+ message: string;
+ conflictingEvent: ScheduleEvent;
+ timeDifference?: number;
+}
+interface DriverAvailability {
+ driverId: string;
+ driverName: string;
+ status: 'available' | 'scheduled' | 'overlapping' | 'tight_turnaround';
+ assignmentCount: number;
+ conflicts: ConflictInfo[];
+ currentAssignments: ScheduleEvent[];
+}
+declare class DriverConflictService {
+ checkDriverConflicts(driverId: string, newEvent: {
+ startTime: string;
+ endTime: string;
+ location: string;
+ }, allSchedules: {
+ [vipId: string]: ScheduleEvent[];
+ }, drivers: any[]): ConflictInfo[];
+ getDriverAvailability(eventTime: {
+ startTime: string;
+ endTime: string;
+ location: string;
+ }, allSchedules: {
+ [vipId: string]: ScheduleEvent[];
+ }, drivers: any[]): DriverAvailability[];
+ private getDriverEvents;
+ private hasTimeOverlap;
+ private getTimeBetweenEvents;
+ getDriverStatusSummary(availability: DriverAvailability): string;
+}
+declare const _default: DriverConflictService;
+export default _default;
+export { DriverAvailability, ConflictInfo, ScheduleEvent };
+//# sourceMappingURL=driverConflictService.d.ts.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/driverConflictService.d.ts.map b/backend-old-20260125/dist/services/driverConflictService.d.ts.map
new file mode 100644
index 0000000..1090255
--- /dev/null
+++ b/backend-old-20260125/dist/services/driverConflictService.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"driverConflictService.d.ts","sourceRoot":"","sources":["../../src/services/driverConflictService.ts"],"names":[],"mappings":"AAAA,UAAU,aAAa;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,YAAY;IACpB,IAAI,EAAE,SAAS,GAAG,kBAAkB,GAAG,cAAc,CAAC;IACtD,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,aAAa,CAAC;IAChC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,WAAW,GAAG,WAAW,GAAG,aAAa,GAAG,kBAAkB,CAAC;IACvE,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,kBAAkB,EAAE,aAAa,EAAE,CAAC;CACrC;AAED,cAAM,qBAAqB;IAGzB,oBAAoB,CAClB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EAClE,YAAY,EAAE;QAAE,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,EAAE,CAAA;KAAE,EAClD,OAAO,EAAE,GAAG,EAAE,GACb,YAAY,EAAE;IA8CjB,qBAAqB,CACnB,SAAS,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EACnE,YAAY,EAAE;QAAE,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,EAAE,CAAA;KAAE,EAClD,OAAO,EAAE,GAAG,EAAE,GACb,kBAAkB,EAAE;IAgCvB,OAAO,CAAC,eAAe;IAsBvB,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,oBAAoB;IAiB5B,sBAAsB,CAAC,YAAY,EAAE,kBAAkB,GAAG,MAAM;CAejE;;AAED,wBAA2C;AAC3C,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/driverConflictService.js b/backend-old-20260125/dist/services/driverConflictService.js
new file mode 100644
index 0000000..3d6eaa8
--- /dev/null
+++ b/backend-old-20260125/dist/services/driverConflictService.js
@@ -0,0 +1,123 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+class DriverConflictService {
+ // Check for conflicts when assigning a driver to an event
+ checkDriverConflicts(driverId, newEvent, allSchedules, drivers) {
+ const conflicts = [];
+ const driver = drivers.find(d => d.id === driverId);
+ if (!driver)
+ return conflicts;
+ // Get all events assigned to this driver
+ const driverEvents = this.getDriverEvents(driverId, allSchedules);
+ const newStartTime = new Date(newEvent.startTime);
+ const newEndTime = new Date(newEvent.endTime);
+ for (const existingEvent of driverEvents) {
+ const existingStart = new Date(existingEvent.startTime);
+ const existingEnd = new Date(existingEvent.endTime);
+ // Check for direct time overlap
+ if (this.hasTimeOverlap(newStartTime, newEndTime, existingStart, existingEnd)) {
+ conflicts.push({
+ type: 'overlap',
+ severity: 'high',
+ message: `Direct time conflict with "${existingEvent.title}" for ${existingEvent.vipName}`,
+ conflictingEvent: existingEvent
+ });
+ }
+ // Check for tight turnaround (less than 15 minutes between events)
+ else {
+ const timeBetween = this.getTimeBetweenEvents(newStartTime, newEndTime, existingStart, existingEnd);
+ if (timeBetween !== null && timeBetween < 15) {
+ conflicts.push({
+ type: 'tight_turnaround',
+ severity: timeBetween < 5 ? 'high' : 'medium',
+ message: `Only ${timeBetween} minutes between events. Previous: "${existingEvent.title}"`,
+ conflictingEvent: existingEvent,
+ timeDifference: timeBetween
+ });
+ }
+ }
+ }
+ return conflicts;
+ }
+ // Get availability status for all drivers for a specific time slot
+ getDriverAvailability(eventTime, allSchedules, drivers) {
+ return drivers.map(driver => {
+ const conflicts = this.checkDriverConflicts(driver.id, eventTime, allSchedules, drivers);
+ const driverEvents = this.getDriverEvents(driver.id, allSchedules);
+ let status = 'available';
+ if (conflicts.length > 0) {
+ const hasOverlap = conflicts.some(c => c.type === 'overlap');
+ const hasTightTurnaround = conflicts.some(c => c.type === 'tight_turnaround');
+ if (hasOverlap) {
+ status = 'overlapping';
+ }
+ else if (hasTightTurnaround) {
+ status = 'tight_turnaround';
+ }
+ }
+ else if (driverEvents.length > 0) {
+ status = 'scheduled';
+ }
+ return {
+ driverId: driver.id,
+ driverName: driver.name,
+ status,
+ assignmentCount: driverEvents.length,
+ conflicts,
+ currentAssignments: driverEvents
+ };
+ });
+ }
+ // Get all events assigned to a specific driver
+ getDriverEvents(driverId, allSchedules) {
+ const driverEvents = [];
+ Object.entries(allSchedules).forEach(([vipId, events]) => {
+ events.forEach(event => {
+ if (event.assignedDriverId === driverId) {
+ driverEvents.push({
+ ...event,
+ vipId,
+ vipName: event.title // We'll need to get actual VIP name from VIP data
+ });
+ }
+ });
+ });
+ // Sort by start time
+ return driverEvents.sort((a, b) => new Date(a.startTime).getTime() - new Date(b.startTime).getTime());
+ }
+ // Check if two time periods overlap
+ hasTimeOverlap(start1, end1, start2, end2) {
+ return start1 < end2 && start2 < end1;
+ }
+ // Get minutes between two events (null if they overlap)
+ getTimeBetweenEvents(newStart, newEnd, existingStart, existingEnd) {
+ // If new event is after existing event
+ if (newStart >= existingEnd) {
+ return Math.floor((newStart.getTime() - existingEnd.getTime()) / (1000 * 60));
+ }
+ // If new event is before existing event
+ else if (newEnd <= existingStart) {
+ return Math.floor((existingStart.getTime() - newEnd.getTime()) / (1000 * 60));
+ }
+ // Events overlap
+ return null;
+ }
+ // Generate summary message for driver status
+ getDriverStatusSummary(availability) {
+ switch (availability.status) {
+ case 'available':
+ return `✅ Fully available (${availability.assignmentCount} assignments)`;
+ case 'scheduled':
+ return `🟡 Has ${availability.assignmentCount} assignment(s) but available for this time`;
+ case 'tight_turnaround':
+ const tightConflict = availability.conflicts.find(c => c.type === 'tight_turnaround');
+ return `⚡ Tight turnaround - ${tightConflict?.timeDifference} min between events`;
+ case 'overlapping':
+ return `🔴 Time conflict with existing assignment`;
+ default:
+ return 'Unknown status';
+ }
+ }
+}
+exports.default = new DriverConflictService();
+//# sourceMappingURL=driverConflictService.js.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/driverConflictService.js.map b/backend-old-20260125/dist/services/driverConflictService.js.map
new file mode 100644
index 0000000..bcca05c
--- /dev/null
+++ b/backend-old-20260125/dist/services/driverConflictService.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"driverConflictService.js","sourceRoot":"","sources":["../../src/services/driverConflictService.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/enhancedDataService.d.ts b/backend-old-20260125/dist/services/enhancedDataService.d.ts
new file mode 100644
index 0000000..0ddb991
--- /dev/null
+++ b/backend-old-20260125/dist/services/enhancedDataService.d.ts
@@ -0,0 +1,60 @@
+interface VipData {
+ id: string;
+ name: string;
+ organization: string;
+ department?: string;
+ transportMode: 'flight' | 'self-driving';
+ expectedArrival?: string;
+ needsAirportPickup?: boolean;
+ needsVenueTransport: boolean;
+ notes?: string;
+ flights?: Array<{
+ flightNumber: string;
+ flightDate: string;
+ segment: number;
+ }>;
+}
+interface DriverData {
+ id: string;
+ name: string;
+ phone: string;
+ department?: string;
+ currentLocation?: {
+ lat: number;
+ lng: number;
+ };
+ assignedVipIds?: string[];
+}
+interface ScheduleEventData {
+ id: string;
+ title: string;
+ location: string;
+ startTime: string;
+ endTime: string;
+ description?: string;
+ assignedDriverId?: string;
+ status: string;
+ type: string;
+}
+declare class EnhancedDataService {
+ getVips(): Promise;
+ addVip(vip: VipData): Promise;
+ updateVip(id: string, vip: Partial): Promise;
+ deleteVip(id: string): Promise;
+ getDrivers(): Promise;
+ addDriver(driver: DriverData): Promise;
+ updateDriver(id: string, driver: Partial): Promise;
+ deleteDriver(id: string): Promise;
+ getSchedule(vipId: string): Promise;
+ addScheduleEvent(vipId: string, event: ScheduleEventData): Promise;
+ updateScheduleEvent(vipId: string, eventId: string, event: ScheduleEventData): Promise;
+ deleteScheduleEvent(vipId: string, eventId: string): Promise;
+ getAllSchedules(): Promise<{
+ [vipId: string]: ScheduleEventData[];
+ }>;
+ getAdminSettings(): Promise;
+ updateAdminSettings(settings: any): Promise;
+}
+declare const _default: EnhancedDataService;
+export default _default;
+//# sourceMappingURL=enhancedDataService.d.ts.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/enhancedDataService.d.ts.map b/backend-old-20260125/dist/services/enhancedDataService.d.ts.map
new file mode 100644
index 0000000..ba3041b
--- /dev/null
+++ b/backend-old-20260125/dist/services/enhancedDataService.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"enhancedDataService.d.ts","sourceRoot":"","sources":["../../src/services/enhancedDataService.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/enhancedDataService.js b/backend-old-20260125/dist/services/enhancedDataService.js
new file mode 100644
index 0000000..01d2f78
--- /dev/null
+++ b/backend-old-20260125/dist/services/enhancedDataService.js
@@ -0,0 +1,571 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const database_1 = __importDefault(require("../config/database"));
+const databaseService_1 = __importDefault(require("./databaseService"));
+class EnhancedDataService {
+ // VIP operations
+ async getVips() {
+ try {
+ const query = `
+ SELECT v.*,
+ COALESCE(
+ json_agg(
+ json_build_object(
+ 'flightNumber', f.flight_number,
+ 'flightDate', f.flight_date,
+ 'segment', f.segment
+ ) ORDER BY f.segment
+ ) FILTER (WHERE f.id IS NOT NULL),
+ '[]'::json
+ ) as flights
+ FROM vips v
+ LEFT JOIN flights f ON v.id = f.vip_id
+ GROUP BY v.id
+ ORDER BY v.name
+ `;
+ const result = await database_1.default.query(query);
+ return result.rows.map(row => ({
+ id: row.id,
+ name: row.name,
+ organization: row.organization,
+ department: row.department,
+ transportMode: row.transport_mode,
+ expectedArrival: row.expected_arrival,
+ needsAirportPickup: row.needs_airport_pickup,
+ needsVenueTransport: row.needs_venue_transport,
+ notes: row.notes,
+ flights: row.flights
+ }));
+ }
+ catch (error) {
+ console.error('❌ Error fetching VIPs:', error);
+ throw error;
+ }
+ }
+ async addVip(vip) {
+ const client = await database_1.default.connect();
+ try {
+ await client.query('BEGIN');
+ // Insert VIP
+ const vipQuery = `
+ INSERT INTO vips (id, name, organization, department, transport_mode, expected_arrival, needs_airport_pickup, needs_venue_transport, notes)
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
+ RETURNING *
+ `;
+ const vipResult = await client.query(vipQuery, [
+ vip.id,
+ vip.name,
+ vip.organization,
+ vip.department || 'Office of Development',
+ vip.transportMode,
+ vip.expectedArrival || null,
+ vip.needsAirportPickup || false,
+ vip.needsVenueTransport,
+ vip.notes || ''
+ ]);
+ // Insert flights if any
+ if (vip.flights && vip.flights.length > 0) {
+ for (const flight of vip.flights) {
+ const flightQuery = `
+ INSERT INTO flights (vip_id, flight_number, flight_date, segment)
+ VALUES ($1, $2, $3, $4)
+ `;
+ await client.query(flightQuery, [
+ vip.id,
+ flight.flightNumber,
+ flight.flightDate,
+ flight.segment
+ ]);
+ }
+ }
+ await client.query('COMMIT');
+ const savedVip = {
+ ...vip,
+ department: vipResult.rows[0].department,
+ transportMode: vipResult.rows[0].transport_mode,
+ expectedArrival: vipResult.rows[0].expected_arrival,
+ needsAirportPickup: vipResult.rows[0].needs_airport_pickup,
+ needsVenueTransport: vipResult.rows[0].needs_venue_transport
+ };
+ return savedVip;
+ }
+ catch (error) {
+ await client.query('ROLLBACK');
+ console.error('❌ Error adding VIP:', error);
+ throw error;
+ }
+ finally {
+ client.release();
+ }
+ }
+ async updateVip(id, vip) {
+ const client = await database_1.default.connect();
+ try {
+ await client.query('BEGIN');
+ // Update VIP
+ const vipQuery = `
+ UPDATE vips
+ SET name = $2, organization = $3, department = $4, transport_mode = $5,
+ expected_arrival = $6, needs_airport_pickup = $7, needs_venue_transport = $8, notes = $9
+ WHERE id = $1
+ RETURNING *
+ `;
+ const vipResult = await client.query(vipQuery, [
+ id,
+ vip.name,
+ vip.organization,
+ vip.department || 'Office of Development',
+ vip.transportMode,
+ vip.expectedArrival || null,
+ vip.needsAirportPickup || false,
+ vip.needsVenueTransport,
+ vip.notes || ''
+ ]);
+ if (vipResult.rows.length === 0) {
+ await client.query('ROLLBACK');
+ return null;
+ }
+ // Delete existing flights and insert new ones
+ await client.query('DELETE FROM flights WHERE vip_id = $1', [id]);
+ if (vip.flights && vip.flights.length > 0) {
+ for (const flight of vip.flights) {
+ const flightQuery = `
+ INSERT INTO flights (vip_id, flight_number, flight_date, segment)
+ VALUES ($1, $2, $3, $4)
+ `;
+ await client.query(flightQuery, [
+ id,
+ flight.flightNumber,
+ flight.flightDate,
+ flight.segment
+ ]);
+ }
+ }
+ await client.query('COMMIT');
+ const updatedVip = {
+ id: vipResult.rows[0].id,
+ name: vipResult.rows[0].name,
+ organization: vipResult.rows[0].organization,
+ department: vipResult.rows[0].department,
+ transportMode: vipResult.rows[0].transport_mode,
+ expectedArrival: vipResult.rows[0].expected_arrival,
+ needsAirportPickup: vipResult.rows[0].needs_airport_pickup,
+ needsVenueTransport: vipResult.rows[0].needs_venue_transport,
+ notes: vipResult.rows[0].notes,
+ flights: vip.flights || []
+ };
+ return updatedVip;
+ }
+ catch (error) {
+ await client.query('ROLLBACK');
+ console.error('❌ Error updating VIP:', error);
+ throw error;
+ }
+ finally {
+ client.release();
+ }
+ }
+ async deleteVip(id) {
+ try {
+ const query = `
+ DELETE FROM vips WHERE id = $1 RETURNING *
+ `;
+ const result = await database_1.default.query(query, [id]);
+ if (result.rows.length === 0) {
+ return null;
+ }
+ const deletedVip = {
+ id: result.rows[0].id,
+ name: result.rows[0].name,
+ organization: result.rows[0].organization,
+ department: result.rows[0].department,
+ transportMode: result.rows[0].transport_mode,
+ expectedArrival: result.rows[0].expected_arrival,
+ needsAirportPickup: result.rows[0].needs_airport_pickup,
+ needsVenueTransport: result.rows[0].needs_venue_transport,
+ notes: result.rows[0].notes
+ };
+ return deletedVip;
+ }
+ catch (error) {
+ console.error('❌ Error deleting VIP:', error);
+ throw error;
+ }
+ }
+ // Driver operations
+ async getDrivers() {
+ try {
+ const query = `
+ SELECT d.*,
+ COALESCE(
+ json_agg(DISTINCT se.vip_id) FILTER (WHERE se.vip_id IS NOT NULL),
+ '[]'::json
+ ) as assigned_vip_ids
+ FROM drivers d
+ LEFT JOIN schedule_events se ON d.id = se.assigned_driver_id
+ GROUP BY d.id
+ ORDER BY d.name
+ `;
+ const result = await database_1.default.query(query);
+ // Get current locations from Redis
+ const driversWithLocations = await Promise.all(result.rows.map(async (row) => {
+ const location = await databaseService_1.default.getDriverLocation(row.id);
+ return {
+ id: row.id,
+ name: row.name,
+ phone: row.phone,
+ department: row.department,
+ currentLocation: location ? { lat: location.lat, lng: location.lng } : { lat: 0, lng: 0 },
+ assignedVipIds: row.assigned_vip_ids || []
+ };
+ }));
+ return driversWithLocations;
+ }
+ catch (error) {
+ console.error('❌ Error fetching drivers:', error);
+ throw error;
+ }
+ }
+ async addDriver(driver) {
+ try {
+ const query = `
+ INSERT INTO drivers (id, name, phone, department)
+ VALUES ($1, $2, $3, $4)
+ RETURNING *
+ `;
+ const result = await database_1.default.query(query, [
+ driver.id,
+ driver.name,
+ driver.phone,
+ driver.department || 'Office of Development'
+ ]);
+ // Store location in Redis if provided
+ if (driver.currentLocation) {
+ await databaseService_1.default.updateDriverLocation(driver.id, driver.currentLocation);
+ }
+ const savedDriver = {
+ id: result.rows[0].id,
+ name: result.rows[0].name,
+ phone: result.rows[0].phone,
+ department: result.rows[0].department,
+ currentLocation: driver.currentLocation || { lat: 0, lng: 0 }
+ };
+ return savedDriver;
+ }
+ catch (error) {
+ console.error('❌ Error adding driver:', error);
+ throw error;
+ }
+ }
+ async updateDriver(id, driver) {
+ try {
+ const query = `
+ UPDATE drivers
+ SET name = $2, phone = $3, department = $4
+ WHERE id = $1
+ RETURNING *
+ `;
+ const result = await database_1.default.query(query, [
+ id,
+ driver.name,
+ driver.phone,
+ driver.department || 'Office of Development'
+ ]);
+ if (result.rows.length === 0) {
+ return null;
+ }
+ // Update location in Redis if provided
+ if (driver.currentLocation) {
+ await databaseService_1.default.updateDriverLocation(id, driver.currentLocation);
+ }
+ const updatedDriver = {
+ id: result.rows[0].id,
+ name: result.rows[0].name,
+ phone: result.rows[0].phone,
+ department: result.rows[0].department,
+ currentLocation: driver.currentLocation || { lat: 0, lng: 0 }
+ };
+ return updatedDriver;
+ }
+ catch (error) {
+ console.error('❌ Error updating driver:', error);
+ throw error;
+ }
+ }
+ async deleteDriver(id) {
+ try {
+ const query = `
+ DELETE FROM drivers WHERE id = $1 RETURNING *
+ `;
+ const result = await database_1.default.query(query, [id]);
+ if (result.rows.length === 0) {
+ return null;
+ }
+ const deletedDriver = {
+ id: result.rows[0].id,
+ name: result.rows[0].name,
+ phone: result.rows[0].phone,
+ department: result.rows[0].department
+ };
+ return deletedDriver;
+ }
+ catch (error) {
+ console.error('❌ Error deleting driver:', error);
+ throw error;
+ }
+ }
+ // Schedule operations
+ async getSchedule(vipId) {
+ try {
+ const query = `
+ SELECT * FROM schedule_events
+ WHERE vip_id = $1
+ ORDER BY start_time
+ `;
+ const result = await database_1.default.query(query, [vipId]);
+ return result.rows.map(row => ({
+ id: row.id,
+ title: row.title,
+ location: row.location,
+ startTime: row.start_time,
+ endTime: row.end_time,
+ description: row.description,
+ assignedDriverId: row.assigned_driver_id,
+ status: row.status,
+ type: row.event_type
+ }));
+ }
+ catch (error) {
+ console.error('❌ Error fetching schedule:', error);
+ throw error;
+ }
+ }
+ async addScheduleEvent(vipId, event) {
+ try {
+ const query = `
+ INSERT INTO schedule_events (id, vip_id, title, location, start_time, end_time, description, assigned_driver_id, status, event_type)
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
+ RETURNING *
+ `;
+ const result = await database_1.default.query(query, [
+ event.id,
+ vipId,
+ event.title,
+ event.location,
+ event.startTime,
+ event.endTime,
+ event.description || '',
+ event.assignedDriverId || null,
+ event.status,
+ event.type
+ ]);
+ const savedEvent = {
+ id: result.rows[0].id,
+ title: result.rows[0].title,
+ location: result.rows[0].location,
+ startTime: result.rows[0].start_time,
+ endTime: result.rows[0].end_time,
+ description: result.rows[0].description,
+ assignedDriverId: result.rows[0].assigned_driver_id,
+ status: result.rows[0].status,
+ type: result.rows[0].event_type
+ };
+ return savedEvent;
+ }
+ catch (error) {
+ console.error('❌ Error adding schedule event:', error);
+ throw error;
+ }
+ }
+ async updateScheduleEvent(vipId, eventId, event) {
+ try {
+ const query = `
+ UPDATE schedule_events
+ SET title = $3, location = $4, start_time = $5, end_time = $6, description = $7, assigned_driver_id = $8, status = $9, event_type = $10
+ WHERE id = $1 AND vip_id = $2
+ RETURNING *
+ `;
+ const result = await database_1.default.query(query, [
+ eventId,
+ vipId,
+ event.title,
+ event.location,
+ event.startTime,
+ event.endTime,
+ event.description || '',
+ event.assignedDriverId || null,
+ event.status,
+ event.type
+ ]);
+ if (result.rows.length === 0) {
+ return null;
+ }
+ const updatedEvent = {
+ id: result.rows[0].id,
+ title: result.rows[0].title,
+ location: result.rows[0].location,
+ startTime: result.rows[0].start_time,
+ endTime: result.rows[0].end_time,
+ description: result.rows[0].description,
+ assignedDriverId: result.rows[0].assigned_driver_id,
+ status: result.rows[0].status,
+ type: result.rows[0].event_type
+ };
+ return updatedEvent;
+ }
+ catch (error) {
+ console.error('❌ Error updating schedule event:', error);
+ throw error;
+ }
+ }
+ async deleteScheduleEvent(vipId, eventId) {
+ try {
+ const query = `
+ DELETE FROM schedule_events
+ WHERE id = $1 AND vip_id = $2
+ RETURNING *
+ `;
+ const result = await database_1.default.query(query, [eventId, vipId]);
+ if (result.rows.length === 0) {
+ return null;
+ }
+ const deletedEvent = {
+ id: result.rows[0].id,
+ title: result.rows[0].title,
+ location: result.rows[0].location,
+ startTime: result.rows[0].start_time,
+ endTime: result.rows[0].end_time,
+ description: result.rows[0].description,
+ assignedDriverId: result.rows[0].assigned_driver_id,
+ status: result.rows[0].status,
+ type: result.rows[0].event_type
+ };
+ return deletedEvent;
+ }
+ catch (error) {
+ console.error('❌ Error deleting schedule event:', error);
+ throw error;
+ }
+ }
+ async getAllSchedules() {
+ try {
+ const query = `
+ SELECT * FROM schedule_events
+ ORDER BY vip_id, start_time
+ `;
+ const result = await database_1.default.query(query);
+ const schedules = {};
+ for (const row of result.rows) {
+ const vipId = row.vip_id;
+ if (!schedules[vipId]) {
+ schedules[vipId] = [];
+ }
+ schedules[vipId].push({
+ id: row.id,
+ title: row.title,
+ location: row.location,
+ startTime: row.start_time,
+ endTime: row.end_time,
+ description: row.description,
+ assignedDriverId: row.assigned_driver_id,
+ status: row.status,
+ type: row.event_type
+ });
+ }
+ return schedules;
+ }
+ catch (error) {
+ console.error('❌ Error fetching all schedules:', error);
+ throw error;
+ }
+ }
+ // Admin settings operations
+ async getAdminSettings() {
+ try {
+ const query = `
+ SELECT setting_key, setting_value FROM admin_settings
+ `;
+ const result = await database_1.default.query(query);
+ // Default settings structure
+ const defaultSettings = {
+ apiKeys: {
+ aviationStackKey: '',
+ googleMapsKey: '',
+ twilioKey: '',
+ googleClientId: '',
+ googleClientSecret: ''
+ },
+ systemSettings: {
+ defaultPickupLocation: '',
+ defaultDropoffLocation: '',
+ timeZone: 'America/New_York',
+ notificationsEnabled: false
+ }
+ };
+ // If no settings exist, return defaults
+ if (result.rows.length === 0) {
+ return defaultSettings;
+ }
+ // Reconstruct nested object from flattened keys
+ const settings = { ...defaultSettings };
+ for (const row of result.rows) {
+ const keys = row.setting_key.split('.');
+ let current = settings;
+ for (let i = 0; i < keys.length - 1; i++) {
+ if (!current[keys[i]]) {
+ current[keys[i]] = {};
+ }
+ current = current[keys[i]];
+ }
+ // Parse boolean values
+ let value = row.setting_value;
+ if (value === 'true')
+ value = true;
+ else if (value === 'false')
+ value = false;
+ current[keys[keys.length - 1]] = value;
+ }
+ return settings;
+ }
+ catch (error) {
+ console.error('❌ Error fetching admin settings:', error);
+ throw error;
+ }
+ }
+ async updateAdminSettings(settings) {
+ try {
+ // Flatten settings and update
+ const flattenSettings = (obj, prefix = '') => {
+ const result = [];
+ for (const [key, value] of Object.entries(obj)) {
+ const fullKey = prefix ? `${prefix}.${key}` : key;
+ if (typeof value === 'object' && value !== null) {
+ result.push(...flattenSettings(value, fullKey));
+ }
+ else {
+ result.push({ key: fullKey, value: String(value) });
+ }
+ }
+ return result;
+ };
+ const flatSettings = flattenSettings(settings);
+ for (const setting of flatSettings) {
+ const query = `
+ INSERT INTO admin_settings (setting_key, setting_value)
+ VALUES ($1, $2)
+ ON CONFLICT (setting_key) DO UPDATE SET setting_value = $2
+ `;
+ await database_1.default.query(query, [setting.key, setting.value]);
+ }
+ }
+ catch (error) {
+ console.error('❌ Error updating admin settings:', error);
+ throw error;
+ }
+ }
+}
+exports.default = new EnhancedDataService();
+//# sourceMappingURL=enhancedDataService.js.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/enhancedDataService.js.map b/backend-old-20260125/dist/services/enhancedDataService.js.map
new file mode 100644
index 0000000..58ade7b
--- /dev/null
+++ b/backend-old-20260125/dist/services/enhancedDataService.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"enhancedDataService.js","sourceRoot":"","sources":["../../src/services/enhancedDataService.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/flightService.d.ts b/backend-old-20260125/dist/services/flightService.d.ts
new file mode 100644
index 0000000..bbce4a9
--- /dev/null
+++ b/backend-old-20260125/dist/services/flightService.d.ts
@@ -0,0 +1,53 @@
+interface FlightData {
+ flightNumber: string;
+ flightDate: string;
+ status: string;
+ airline?: string;
+ aircraft?: string;
+ departure: {
+ airport: string;
+ airportName?: string;
+ scheduled: string;
+ estimated?: string;
+ actual?: string;
+ terminal?: string;
+ gate?: string;
+ };
+ arrival: {
+ airport: string;
+ airportName?: string;
+ scheduled: string;
+ estimated?: string;
+ actual?: string;
+ terminal?: string;
+ gate?: string;
+ };
+ delay?: number;
+ lastUpdated: string;
+ source: 'google' | 'aviationstack' | 'not_found';
+}
+interface FlightSearchParams {
+ flightNumber: string;
+ date: string;
+ departureAirport?: string;
+ arrivalAirport?: string;
+}
+declare class FlightService {
+ private flightCache;
+ private updateIntervals;
+ constructor();
+ getFlightInfo(params: FlightSearchParams): Promise;
+ private scrapeGoogleFlights;
+ private getFromAviationStack;
+ startPeriodicUpdates(params: FlightSearchParams, intervalMinutes?: number): void;
+ stopPeriodicUpdates(key: string): void;
+ getMultipleFlights(flightParams: FlightSearchParams[]): Promise<{
+ [key: string]: FlightData | null;
+ }>;
+ private normalizeStatus;
+ cleanup(): void;
+}
+declare const _default: FlightService;
+export default _default;
+export { FlightData, FlightSearchParams };
+//# sourceMappingURL=flightService.d.ts.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/flightService.d.ts.map b/backend-old-20260125/dist/services/flightService.d.ts.map
new file mode 100644
index 0000000..da42d58
--- /dev/null
+++ b/backend-old-20260125/dist/services/flightService.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"flightService.d.ts","sourceRoot":"","sources":["../../src/services/flightService.ts"],"names":[],"mappings":"AAGA,UAAU,UAAU;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE;QACT,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,OAAO,EAAE;QACP,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,QAAQ,GAAG,eAAe,GAAG,WAAW,CAAC;CAClD;AAED,UAAU,kBAAkB;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,cAAM,aAAa;IACjB,OAAO,CAAC,WAAW,CAAiE;IACpF,OAAO,CAAC,eAAe,CAA0C;;IAO3D,aAAa,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;YAkC7D,mBAAmB;YAiBnB,oBAAoB;IAiGlC,oBAAoB,CAAC,MAAM,EAAE,kBAAkB,EAAE,eAAe,GAAE,MAAU,GAAG,IAAI;IAoBnF,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAShC,kBAAkB,CAAC,YAAY,EAAE,kBAAkB,EAAE,GAAG,OAAO,CAAC;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAAA;KAAE,CAAC;IAY3G,OAAO,CAAC,eAAe;IAcvB,OAAO,IAAI,IAAI;CAOhB;;AAED,wBAAmC;AACnC,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,CAAC"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/flightService.js b/backend-old-20260125/dist/services/flightService.js
new file mode 100644
index 0000000..9d5f213
--- /dev/null
+++ b/backend-old-20260125/dist/services/flightService.js
@@ -0,0 +1,196 @@
+"use strict";
+// Real Flight tracking service with Google scraping
+// No mock data - only real flight information
+Object.defineProperty(exports, "__esModule", { value: true });
+class FlightService {
+ constructor() {
+ this.flightCache = new Map();
+ this.updateIntervals = new Map();
+ // No API keys needed for Google scraping
+ }
+ // Real flight lookup - no mock data
+ async getFlightInfo(params) {
+ const cacheKey = `${params.flightNumber}_${params.date}`;
+ // Check cache first (shorter cache for real data)
+ const cached = this.flightCache.get(cacheKey);
+ if (cached && cached.expires > Date.now()) {
+ return cached.data;
+ }
+ try {
+ // Try Google scraping first
+ let flightData = await this.scrapeGoogleFlights(params);
+ // If Google fails, try AviationStack (if API key available)
+ if (!flightData) {
+ flightData = await this.getFromAviationStack(params);
+ }
+ // Cache the result for 2 minutes (shorter for real data)
+ if (flightData) {
+ this.flightCache.set(cacheKey, {
+ data: flightData,
+ expires: Date.now() + (2 * 60 * 1000)
+ });
+ }
+ return flightData;
+ }
+ catch (error) {
+ console.error('Error fetching flight data:', error);
+ return null; // Return null instead of mock data
+ }
+ }
+ // Google Flights scraping implementation
+ async scrapeGoogleFlights(params) {
+ try {
+ // Google Flights URL format
+ const googleUrl = `https://www.google.com/travel/flights/search?tfs=CBwQAhoeEgoyMDI1LTA3LTAxagcIARIDTEFYcgcIARIDSkZLQAFIAXABggELCP___________wFAAUgBmAEB&hl=en`;
+ // For now, return null to indicate no real scraping implementation
+ // In production, you would implement actual web scraping here
+ console.log(`Would scrape Google for flight ${params.flightNumber} on ${params.date}`);
+ return null;
+ }
+ catch (error) {
+ console.error('Google scraping error:', error);
+ return null;
+ }
+ }
+ // AviationStack API integration (only if API key available)
+ async getFromAviationStack(params) {
+ const apiKey = process.env.AVIATIONSTACK_API_KEY;
+ console.log('Checking AviationStack API key:', apiKey ? `Key present (${apiKey.length} chars)` : 'No key');
+ if (!apiKey || apiKey === 'demo_key' || apiKey === '') {
+ console.log('No valid AviationStack API key available');
+ return null; // No API key available
+ }
+ try {
+ // Format flight number: Remove spaces and convert to uppercase
+ const formattedFlightNumber = params.flightNumber.replace(/\s+/g, '').toUpperCase();
+ console.log(`Formatted flight number: ${params.flightNumber} -> ${formattedFlightNumber}`);
+ // Note: Free tier doesn't support date filtering, so we get recent flights
+ // For future dates, this won't work well - consider upgrading subscription
+ const url = `http://api.aviationstack.com/v1/flights?access_key=${apiKey}&flight_iata=${formattedFlightNumber}&limit=10`;
+ console.log('AviationStack API URL:', url.replace(apiKey, '***'));
+ console.log('Note: Free tier returns recent flights only, not future scheduled flights');
+ const response = await fetch(url);
+ const data = await response.json();
+ console.log('AviationStack response status:', response.status);
+ if (!response.ok) {
+ console.error('AviationStack API error - HTTP status:', response.status);
+ return null;
+ }
+ // Check for API errors in response
+ if (data.error) {
+ console.error('AviationStack API error:', data.error);
+ return null;
+ }
+ if (data.data && data.data.length > 0) {
+ // This is a valid flight number that exists!
+ console.log(`✅ Valid flight number: ${formattedFlightNumber} exists in the system`);
+ // Try to find a flight matching the requested date
+ let flight = data.data.find((f) => f.flight_date === params.date);
+ // If no exact date match, use most recent for validation
+ if (!flight) {
+ flight = data.data[0];
+ console.log(`ℹ️ Flight ${formattedFlightNumber} is valid`);
+ console.log(`Recent flight: ${flight.departure.airport} → ${flight.arrival.airport}`);
+ console.log(`Operated by: ${flight.airline?.name || 'Unknown'}`);
+ console.log(`Note: Showing recent data from ${flight.flight_date} for validation`);
+ }
+ else {
+ console.log(`✅ Flight found for exact date: ${params.date}`);
+ }
+ console.log('Flight route:', `${flight.departure.iata} → ${flight.arrival.iata}`);
+ console.log('Status:', flight.flight_status);
+ return {
+ flightNumber: flight.flight.iata,
+ flightDate: flight.flight_date,
+ status: this.normalizeStatus(flight.flight_status),
+ airline: flight.airline?.name,
+ aircraft: flight.aircraft?.registration,
+ departure: {
+ airport: flight.departure.iata,
+ airportName: flight.departure.airport,
+ scheduled: flight.departure.scheduled,
+ estimated: flight.departure.estimated,
+ actual: flight.departure.actual,
+ terminal: flight.departure.terminal,
+ gate: flight.departure.gate
+ },
+ arrival: {
+ airport: flight.arrival.iata,
+ airportName: flight.arrival.airport,
+ scheduled: flight.arrival.scheduled,
+ estimated: flight.arrival.estimated,
+ actual: flight.arrival.actual,
+ terminal: flight.arrival.terminal,
+ gate: flight.arrival.gate
+ },
+ delay: flight.departure.delay || 0,
+ lastUpdated: new Date().toISOString(),
+ source: 'aviationstack'
+ };
+ }
+ console.log(`❌ Invalid flight number: ${formattedFlightNumber} not found`);
+ console.log('This flight number does not exist or has not operated recently');
+ return null;
+ }
+ catch (error) {
+ console.error('AviationStack API error:', error);
+ return null;
+ }
+ }
+ // Start periodic updates for a flight
+ startPeriodicUpdates(params, intervalMinutes = 5) {
+ const key = `${params.flightNumber}_${params.date}`;
+ // Clear existing interval if any
+ this.stopPeriodicUpdates(key);
+ // Set up new interval
+ const interval = setInterval(async () => {
+ try {
+ await this.getFlightInfo(params); // This will update the cache
+ console.log(`Updated flight data for ${params.flightNumber} on ${params.date}`);
+ }
+ catch (error) {
+ console.error(`Error updating flight ${params.flightNumber}:`, error);
+ }
+ }, intervalMinutes * 60 * 1000);
+ this.updateIntervals.set(key, interval);
+ }
+ // Stop periodic updates for a flight
+ stopPeriodicUpdates(key) {
+ const interval = this.updateIntervals.get(key);
+ if (interval) {
+ clearInterval(interval);
+ this.updateIntervals.delete(key);
+ }
+ }
+ // Get multiple flights with date specificity
+ async getMultipleFlights(flightParams) {
+ const results = {};
+ for (const params of flightParams) {
+ const key = `${params.flightNumber}_${params.date}`;
+ results[key] = await this.getFlightInfo(params);
+ }
+ return results;
+ }
+ // Normalize flight status across different APIs
+ normalizeStatus(status) {
+ const statusMap = {
+ 'scheduled': 'scheduled',
+ 'active': 'active',
+ 'landed': 'landed',
+ 'cancelled': 'cancelled',
+ 'incident': 'delayed',
+ 'diverted': 'diverted'
+ };
+ return statusMap[status.toLowerCase()] || status;
+ }
+ // Clean up resources
+ cleanup() {
+ for (const [key, interval] of this.updateIntervals) {
+ clearInterval(interval);
+ }
+ this.updateIntervals.clear();
+ this.flightCache.clear();
+ }
+}
+exports.default = new FlightService();
+//# sourceMappingURL=flightService.js.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/flightService.js.map b/backend-old-20260125/dist/services/flightService.js.map
new file mode 100644
index 0000000..0b445d1
--- /dev/null
+++ b/backend-old-20260125/dist/services/flightService.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"flightService.js","sourceRoot":"","sources":["../../src/services/flightService.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/flightTrackingScheduler.d.ts b/backend-old-20260125/dist/services/flightTrackingScheduler.d.ts
new file mode 100644
index 0000000..e503b64
--- /dev/null
+++ b/backend-old-20260125/dist/services/flightTrackingScheduler.d.ts
@@ -0,0 +1,16 @@
+declare class FlightTrackingScheduler {
+ private trackingSchedule;
+ private checkIntervals;
+ private flightService;
+ constructor(flightService: any);
+ addVipFlights(vipId: string, vipName: string, flights: any[]): void;
+ removeVipFlights(vipId: string): void;
+ private updateTrackingSchedules;
+ private setupDateTracking;
+ private performBatchCheck;
+ private stopDateTracking;
+ getTrackingStatus(): any;
+ cleanup(): void;
+}
+export default FlightTrackingScheduler;
+//# sourceMappingURL=flightTrackingScheduler.d.ts.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/flightTrackingScheduler.d.ts.map b/backend-old-20260125/dist/services/flightTrackingScheduler.d.ts.map
new file mode 100644
index 0000000..4df7421
--- /dev/null
+++ b/backend-old-20260125/dist/services/flightTrackingScheduler.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"flightTrackingScheduler.d.ts","sourceRoot":"","sources":["../../src/services/flightTrackingScheduler.ts"],"names":[],"mappings":"AAoBA,cAAM,uBAAuB;IAC3B,OAAO,CAAC,gBAAgB,CAAwB;IAChD,OAAO,CAAC,cAAc,CAA0C;IAChE,OAAO,CAAC,aAAa,CAAM;gBAEf,aAAa,EAAE,GAAG;IAK9B,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE;IAoC5D,gBAAgB,CAAC,KAAK,EAAE,MAAM;IAgB9B,OAAO,CAAC,uBAAuB;IAY/B,OAAO,CAAC,iBAAiB;YAsDX,iBAAiB;IAwF/B,OAAO,CAAC,gBAAgB;IAcxB,iBAAiB,IAAI,GAAG;IA0BxB,OAAO;CAKR;AAED,eAAe,uBAAuB,CAAC"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/flightTrackingScheduler.js b/backend-old-20260125/dist/services/flightTrackingScheduler.js
new file mode 100644
index 0000000..cb8b41e
--- /dev/null
+++ b/backend-old-20260125/dist/services/flightTrackingScheduler.js
@@ -0,0 +1,219 @@
+"use strict";
+// Flight Tracking Scheduler Service
+// Efficiently batches flight API calls and manages tracking schedules
+Object.defineProperty(exports, "__esModule", { value: true });
+class FlightTrackingScheduler {
+ constructor(flightService) {
+ this.trackingSchedule = {};
+ this.checkIntervals = new Map();
+ this.flightService = flightService;
+ }
+ // Add flights for a VIP to the tracking schedule
+ addVipFlights(vipId, vipName, flights) {
+ flights.forEach(flight => {
+ const key = flight.flightDate;
+ if (!this.trackingSchedule[key]) {
+ this.trackingSchedule[key] = [];
+ }
+ // Check if this flight is already being tracked
+ const existingIndex = this.trackingSchedule[key].findIndex(f => f.flightNumber === flight.flightNumber && f.vipId === vipId);
+ const scheduledFlight = {
+ vipId,
+ vipName,
+ flightNumber: flight.flightNumber,
+ flightDate: flight.flightDate,
+ segment: flight.segment,
+ scheduledDeparture: flight.validationData?.departure?.scheduled
+ };
+ if (existingIndex >= 0) {
+ // Update existing entry
+ this.trackingSchedule[key][existingIndex] = scheduledFlight;
+ }
+ else {
+ // Add new entry
+ this.trackingSchedule[key].push(scheduledFlight);
+ }
+ });
+ // Start or update tracking for affected dates
+ this.updateTrackingSchedules();
+ }
+ // Remove VIP flights from tracking
+ removeVipFlights(vipId) {
+ Object.keys(this.trackingSchedule).forEach(date => {
+ this.trackingSchedule[date] = this.trackingSchedule[date].filter(f => f.vipId !== vipId);
+ // Remove empty dates
+ if (this.trackingSchedule[date].length === 0) {
+ delete this.trackingSchedule[date];
+ }
+ });
+ this.updateTrackingSchedules();
+ }
+ // Update tracking schedules based on current flights
+ updateTrackingSchedules() {
+ // Clear existing intervals
+ this.checkIntervals.forEach(interval => clearInterval(interval));
+ this.checkIntervals.clear();
+ // Set up tracking for each date
+ Object.keys(this.trackingSchedule).forEach(date => {
+ this.setupDateTracking(date);
+ });
+ }
+ // Set up tracking for a specific date
+ setupDateTracking(date) {
+ const flights = this.trackingSchedule[date];
+ if (!flights || flights.length === 0)
+ return;
+ // Check if we should start tracking (4 hours before first flight)
+ const now = new Date();
+ const dateObj = new Date(date + 'T00:00:00');
+ // Find earliest departure time
+ let earliestDeparture = null;
+ flights.forEach(flight => {
+ if (flight.scheduledDeparture) {
+ const depTime = new Date(flight.scheduledDeparture);
+ if (!earliestDeparture || depTime < earliestDeparture) {
+ earliestDeparture = depTime;
+ }
+ }
+ });
+ // If no departure times, assume noon
+ if (!earliestDeparture) {
+ earliestDeparture = new Date(date + 'T12:00:00');
+ }
+ // Start tracking 4 hours before earliest departure
+ const trackingStartTime = new Date(earliestDeparture.getTime() - 4 * 60 * 60 * 1000);
+ // If tracking should have started, begin immediately
+ if (now >= trackingStartTime) {
+ this.performBatchCheck(date);
+ // Set up recurring checks every 60 minutes (or 30 if any delays)
+ const interval = setInterval(() => {
+ this.performBatchCheck(date);
+ }, 60 * 60 * 1000); // 60 minutes
+ this.checkIntervals.set(date, interval);
+ }
+ else {
+ // Schedule first check for tracking start time
+ const timeUntilStart = trackingStartTime.getTime() - now.getTime();
+ setTimeout(() => {
+ this.performBatchCheck(date);
+ // Then set up recurring checks
+ const interval = setInterval(() => {
+ this.performBatchCheck(date);
+ }, 60 * 60 * 1000);
+ this.checkIntervals.set(date, interval);
+ }, timeUntilStart);
+ }
+ }
+ // Perform batch check for all flights on a date
+ async performBatchCheck(date) {
+ const flights = this.trackingSchedule[date];
+ if (!flights || flights.length === 0)
+ return;
+ console.log(`\n=== Batch Flight Check for ${date} ===`);
+ console.log(`Checking ${flights.length} flights...`);
+ // Filter out flights that have already landed
+ const activeFlights = flights.filter(f => !f.hasLanded);
+ if (activeFlights.length === 0) {
+ console.log('All flights have landed. Stopping tracking for this date.');
+ this.stopDateTracking(date);
+ return;
+ }
+ // Get unique flight numbers to check
+ const uniqueFlights = Array.from(new Set(activeFlights.map(f => f.flightNumber)));
+ console.log(`Unique flight numbers to check: ${uniqueFlights.join(', ')}`);
+ try {
+ // Make batch API call
+ const flightParams = uniqueFlights.map(flightNumber => ({
+ flightNumber,
+ date
+ }));
+ const results = await this.flightService.getMultipleFlights(flightParams);
+ // Update flight statuses
+ let hasDelays = false;
+ let allLanded = true;
+ activeFlights.forEach(flight => {
+ const key = `${flight.flightNumber}_${date}`;
+ const data = results[key];
+ if (data) {
+ flight.lastChecked = new Date();
+ flight.status = data.status;
+ if (data.status === 'landed') {
+ flight.hasLanded = true;
+ console.log(`✅ ${flight.flightNumber} has landed`);
+ }
+ else {
+ allLanded = false;
+ if (data.delay && data.delay > 0) {
+ hasDelays = true;
+ console.log(`⚠️ ${flight.flightNumber} is delayed by ${data.delay} minutes`);
+ }
+ }
+ // Log status for each VIP
+ console.log(` VIP: ${flight.vipName} - Flight ${flight.segment}: ${flight.flightNumber} - Status: ${data.status}`);
+ }
+ });
+ // Update check frequency if delays detected
+ if (hasDelays && this.checkIntervals.has(date)) {
+ console.log('Delays detected - increasing check frequency to 30 minutes');
+ clearInterval(this.checkIntervals.get(date));
+ const interval = setInterval(() => {
+ this.performBatchCheck(date);
+ }, 30 * 60 * 1000); // 30 minutes
+ this.checkIntervals.set(date, interval);
+ }
+ // Stop tracking if all flights have landed
+ if (allLanded) {
+ console.log('All flights have landed. Stopping tracking for this date.');
+ this.stopDateTracking(date);
+ }
+ // Calculate next check time
+ const nextCheckTime = new Date(Date.now() + (hasDelays ? 30 : 60) * 60 * 1000);
+ console.log(`Next check scheduled for: ${nextCheckTime.toLocaleTimeString()}`);
+ }
+ catch (error) {
+ console.error('Error performing batch flight check:', error);
+ }
+ }
+ // Stop tracking for a specific date
+ stopDateTracking(date) {
+ const interval = this.checkIntervals.get(date);
+ if (interval) {
+ clearInterval(interval);
+ this.checkIntervals.delete(date);
+ }
+ // Mark all flights as completed
+ if (this.trackingSchedule[date]) {
+ this.trackingSchedule[date].forEach(f => f.hasLanded = true);
+ }
+ }
+ // Get current tracking status
+ getTrackingStatus() {
+ const status = {};
+ Object.entries(this.trackingSchedule).forEach(([date, flights]) => {
+ const activeFlights = flights.filter(f => !f.hasLanded);
+ const landedFlights = flights.filter(f => f.hasLanded);
+ status[date] = {
+ totalFlights: flights.length,
+ activeFlights: activeFlights.length,
+ landedFlights: landedFlights.length,
+ flights: flights.map(f => ({
+ vipName: f.vipName,
+ flightNumber: f.flightNumber,
+ segment: f.segment,
+ status: f.status || 'Not checked yet',
+ lastChecked: f.lastChecked,
+ hasLanded: f.hasLanded
+ }))
+ };
+ });
+ return status;
+ }
+ // Clean up all tracking
+ cleanup() {
+ this.checkIntervals.forEach(interval => clearInterval(interval));
+ this.checkIntervals.clear();
+ this.trackingSchedule = {};
+ }
+}
+exports.default = FlightTrackingScheduler;
+//# sourceMappingURL=flightTrackingScheduler.js.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/flightTrackingScheduler.js.map b/backend-old-20260125/dist/services/flightTrackingScheduler.js.map
new file mode 100644
index 0000000..aa3f601
--- /dev/null
+++ b/backend-old-20260125/dist/services/flightTrackingScheduler.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"flightTrackingScheduler.js","sourceRoot":"","sources":["../../src/services/flightTrackingScheduler.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/jwtKeyManager.d.ts b/backend-old-20260125/dist/services/jwtKeyManager.d.ts
new file mode 100644
index 0000000..9283519
--- /dev/null
+++ b/backend-old-20260125/dist/services/jwtKeyManager.d.ts
@@ -0,0 +1,38 @@
+export interface User {
+ id: string;
+ google_id: string;
+ email: string;
+ name: string;
+ profile_picture_url?: string;
+ role: 'driver' | 'coordinator' | 'administrator';
+ status?: 'pending' | 'active' | 'deactivated';
+ created_at?: string;
+ last_login?: string;
+ is_active?: boolean;
+ updated_at?: string;
+ approval_status?: string;
+ onboardingData?: any;
+}
+declare class JWTKeyManager {
+ private currentSecret;
+ private previousSecret;
+ private rotationInterval;
+ private gracePeriodTimeout;
+ constructor();
+ private generateSecret;
+ private startRotation;
+ private rotateKey;
+ generateToken(user: User): string;
+ verifyToken(token: string): User | null;
+ getStatus(): {
+ hasCurrentKey: boolean;
+ hasPreviousKey: boolean;
+ rotationActive: boolean;
+ gracePeriodActive: boolean;
+ };
+ destroy(): void;
+ forceRotation(): void;
+}
+export declare const jwtKeyManager: JWTKeyManager;
+export default jwtKeyManager;
+//# sourceMappingURL=jwtKeyManager.d.ts.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/jwtKeyManager.d.ts.map b/backend-old-20260125/dist/services/jwtKeyManager.d.ts.map
new file mode 100644
index 0000000..c06f65c
--- /dev/null
+++ b/backend-old-20260125/dist/services/jwtKeyManager.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"jwtKeyManager.d.ts","sourceRoot":"","sources":["../../src/services/jwtKeyManager.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,IAAI,EAAE,QAAQ,GAAG,aAAa,GAAG,eAAe,CAAC;IACjD,MAAM,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,aAAa,CAAC;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,GAAG,CAAC;CACtB;AAED,cAAM,aAAa;IACjB,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,gBAAgB,CAA+B;IACvD,OAAO,CAAC,kBAAkB,CAA+B;;IAQzD,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,aAAa;IAerB,OAAO,CAAC,SAAS;IAuBjB,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM;IAqBjC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAqDvC,SAAS;;;;;;IAUT,OAAO;IAiBP,aAAa;CAId;AAGD,eAAO,MAAM,aAAa,eAAsB,CAAC;AAWjD,eAAe,aAAa,CAAC"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/jwtKeyManager.js b/backend-old-20260125/dist/services/jwtKeyManager.js
new file mode 100644
index 0000000..261c64d
--- /dev/null
+++ b/backend-old-20260125/dist/services/jwtKeyManager.js
@@ -0,0 +1,158 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.jwtKeyManager = void 0;
+const crypto_1 = __importDefault(require("crypto"));
+const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
+class JWTKeyManager {
+ constructor() {
+ this.previousSecret = null;
+ this.rotationInterval = null;
+ this.gracePeriodTimeout = null;
+ console.log('🔑 Initializing JWT Key Manager with automatic rotation');
+ this.currentSecret = this.generateSecret();
+ this.startRotation();
+ }
+ generateSecret() {
+ const secret = crypto_1.default.randomBytes(64).toString('hex');
+ console.log('🔄 Generated new JWT signing key (length:', secret.length, 'chars)');
+ return secret;
+ }
+ startRotation() {
+ // Rotate every 24 hours (86400000 ms)
+ this.rotationInterval = setInterval(() => {
+ this.rotateKey();
+ }, 24 * 60 * 60 * 1000);
+ console.log('⏰ JWT key rotation scheduled every 24 hours');
+ // Also rotate on startup after 1 hour to test the system
+ setTimeout(() => {
+ console.log('🧪 Performing initial key rotation test...');
+ this.rotateKey();
+ }, 60 * 60 * 1000); // 1 hour
+ }
+ rotateKey() {
+ console.log('🔄 Rotating JWT signing key...');
+ // Store current secret as previous
+ this.previousSecret = this.currentSecret;
+ // Generate new current secret
+ this.currentSecret = this.generateSecret();
+ console.log('✅ JWT key rotation completed. Grace period: 24 hours');
+ // Clear any existing grace period timeout
+ if (this.gracePeriodTimeout) {
+ clearTimeout(this.gracePeriodTimeout);
+ }
+ // Clean up previous secret after 24 hours (grace period)
+ this.gracePeriodTimeout = setTimeout(() => {
+ this.previousSecret = null;
+ console.log('🧹 Grace period ended. Previous JWT key cleaned up');
+ }, 24 * 60 * 60 * 1000);
+ }
+ generateToken(user) {
+ const payload = {
+ id: user.id,
+ google_id: user.google_id,
+ email: user.email,
+ name: user.name,
+ profile_picture_url: user.profile_picture_url,
+ role: user.role,
+ status: user.status,
+ approval_status: user.approval_status,
+ onboardingData: user.onboardingData,
+ iat: Math.floor(Date.now() / 1000) // Issued at time
+ };
+ return jsonwebtoken_1.default.sign(payload, this.currentSecret, {
+ expiresIn: '24h',
+ issuer: 'vip-coordinator',
+ audience: 'vip-coordinator-users'
+ });
+ }
+ verifyToken(token) {
+ try {
+ // Try current secret first
+ const decoded = jsonwebtoken_1.default.verify(token, this.currentSecret, {
+ issuer: 'vip-coordinator',
+ audience: 'vip-coordinator-users'
+ });
+ return {
+ id: decoded.id,
+ google_id: decoded.google_id,
+ email: decoded.email,
+ name: decoded.name,
+ profile_picture_url: decoded.profile_picture_url,
+ role: decoded.role,
+ status: decoded.status,
+ approval_status: decoded.approval_status,
+ onboardingData: decoded.onboardingData
+ };
+ }
+ catch (error) {
+ // Try previous secret during grace period
+ if (this.previousSecret) {
+ try {
+ const decoded = jsonwebtoken_1.default.verify(token, this.previousSecret, {
+ issuer: 'vip-coordinator',
+ audience: 'vip-coordinator-users'
+ });
+ console.log('🔄 Token verified using previous key (grace period)');
+ return {
+ id: decoded.id,
+ google_id: decoded.google_id,
+ email: decoded.email,
+ name: decoded.name,
+ profile_picture_url: decoded.profile_picture_url,
+ role: decoded.role,
+ status: decoded.status,
+ approval_status: decoded.approval_status,
+ onboardingData: decoded.onboardingData
+ };
+ }
+ catch (gracePeriodError) {
+ console.log('❌ Token verification failed with both current and previous keys');
+ return null;
+ }
+ }
+ console.log('❌ Token verification failed:', error instanceof Error ? error.message : 'Unknown error');
+ return null;
+ }
+ }
+ // Get status for monitoring/debugging
+ getStatus() {
+ return {
+ hasCurrentKey: !!this.currentSecret,
+ hasPreviousKey: !!this.previousSecret,
+ rotationActive: !!this.rotationInterval,
+ gracePeriodActive: !!this.gracePeriodTimeout
+ };
+ }
+ // Cleanup on shutdown
+ destroy() {
+ console.log('🛑 Shutting down JWT Key Manager...');
+ if (this.rotationInterval) {
+ clearInterval(this.rotationInterval);
+ this.rotationInterval = null;
+ }
+ if (this.gracePeriodTimeout) {
+ clearTimeout(this.gracePeriodTimeout);
+ this.gracePeriodTimeout = null;
+ }
+ console.log('✅ JWT Key Manager shutdown complete');
+ }
+ // Manual rotation for testing/emergency
+ forceRotation() {
+ console.log('🚨 Manual key rotation triggered');
+ this.rotateKey();
+ }
+}
+// Singleton instance
+exports.jwtKeyManager = new JWTKeyManager();
+// Graceful shutdown handling
+process.on('SIGTERM', () => {
+ exports.jwtKeyManager.destroy();
+});
+process.on('SIGINT', () => {
+ exports.jwtKeyManager.destroy();
+});
+exports.default = exports.jwtKeyManager;
+//# sourceMappingURL=jwtKeyManager.js.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/jwtKeyManager.js.map b/backend-old-20260125/dist/services/jwtKeyManager.js.map
new file mode 100644
index 0000000..475d9f9
--- /dev/null
+++ b/backend-old-20260125/dist/services/jwtKeyManager.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"jwtKeyManager.js","sourceRoot":"","sources":["../../src/services/jwtKeyManager.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/scheduleValidationService.d.ts b/backend-old-20260125/dist/services/scheduleValidationService.d.ts
new file mode 100644
index 0000000..63a4cbf
--- /dev/null
+++ b/backend-old-20260125/dist/services/scheduleValidationService.d.ts
@@ -0,0 +1,30 @@
+interface ValidationError {
+ field: string;
+ message: string;
+ code: string;
+}
+interface ScheduleEvent {
+ title: string;
+ startTime: string;
+ endTime: string;
+ location: string;
+ type: string;
+}
+declare class ScheduleValidationService {
+ validateEvent(event: ScheduleEvent, isEdit?: boolean): ValidationError[];
+ validateEventSequence(events: ScheduleEvent[]): ValidationError[];
+ getErrorSummary(errors: ValidationError[]): string;
+ isCriticalError(error: ValidationError): boolean;
+ categorizeErrors(errors: ValidationError[]): {
+ critical: ValidationError[];
+ warnings: ValidationError[];
+ };
+ validateTimeFormat(timeString: string): {
+ isValid: boolean;
+ suggestion?: string;
+ };
+}
+declare const _default: ScheduleValidationService;
+export default _default;
+export { ValidationError, ScheduleEvent };
+//# sourceMappingURL=scheduleValidationService.d.ts.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/scheduleValidationService.d.ts.map b/backend-old-20260125/dist/services/scheduleValidationService.d.ts.map
new file mode 100644
index 0000000..45eed50
--- /dev/null
+++ b/backend-old-20260125/dist/services/scheduleValidationService.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"scheduleValidationService.d.ts","sourceRoot":"","sources":["../../src/services/scheduleValidationService.ts"],"names":[],"mappings":"AAAA,UAAU,eAAe;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,aAAa;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,cAAM,yBAAyB;IAG7B,aAAa,CAAC,KAAK,EAAE,aAAa,EAAE,MAAM,GAAE,OAAe,GAAG,eAAe,EAAE;IAuJ/E,qBAAqB,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,eAAe,EAAE;IA6BjE,eAAe,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM;IAalD,eAAe,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO;IAMhD,gBAAgB,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG;QAAE,QAAQ,EAAE,eAAe,EAAE,CAAC;QAAC,QAAQ,EAAE,eAAe,EAAE,CAAA;KAAE;IAgBzG,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE;CAYlF;;AAED,wBAA+C;AAC/C,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,CAAC"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/scheduleValidationService.js b/backend-old-20260125/dist/services/scheduleValidationService.js
new file mode 100644
index 0000000..f64790d
--- /dev/null
+++ b/backend-old-20260125/dist/services/scheduleValidationService.js
@@ -0,0 +1,200 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+class ScheduleValidationService {
+ // Validate a single schedule event
+ validateEvent(event, isEdit = false) {
+ const errors = [];
+ const now = new Date();
+ const startTime = new Date(event.startTime);
+ const endTime = new Date(event.endTime);
+ // 1. Check if dates are valid
+ if (isNaN(startTime.getTime())) {
+ errors.push({
+ field: 'startTime',
+ message: 'Start time is not a valid date',
+ code: 'INVALID_START_DATE'
+ });
+ }
+ if (isNaN(endTime.getTime())) {
+ errors.push({
+ field: 'endTime',
+ message: 'End time is not a valid date',
+ code: 'INVALID_END_DATE'
+ });
+ }
+ // If dates are invalid, return early
+ if (errors.length > 0) {
+ return errors;
+ }
+ // 2. Check if start time is in the future (with 5-minute grace period for edits)
+ const graceMinutes = isEdit ? 5 : 0;
+ const minimumStartTime = new Date(now.getTime() + (graceMinutes * 60 * 1000));
+ if (startTime < minimumStartTime) {
+ errors.push({
+ field: 'startTime',
+ message: isEdit
+ ? 'Start time must be at least 5 minutes in the future for edits'
+ : 'Start time must be in the future',
+ code: 'START_TIME_IN_PAST'
+ });
+ }
+ // 3. Check if end time is after start time
+ if (endTime <= startTime) {
+ errors.push({
+ field: 'endTime',
+ message: 'End time must be after start time',
+ code: 'END_BEFORE_START'
+ });
+ }
+ // 4. Check minimum event duration (5 minutes)
+ const durationMinutes = (endTime.getTime() - startTime.getTime()) / (1000 * 60);
+ if (durationMinutes < 5) {
+ errors.push({
+ field: 'endTime',
+ message: 'Event must be at least 5 minutes long',
+ code: 'DURATION_TOO_SHORT'
+ });
+ }
+ // 5. Check maximum event duration (24 hours)
+ if (durationMinutes > (24 * 60)) {
+ errors.push({
+ field: 'endTime',
+ message: 'Event cannot be longer than 24 hours',
+ code: 'DURATION_TOO_LONG'
+ });
+ }
+ // 6. Check if end time is in the future
+ if (endTime < now) {
+ errors.push({
+ field: 'endTime',
+ message: 'End time must be in the future',
+ code: 'END_TIME_IN_PAST'
+ });
+ }
+ // 7. Validate required fields
+ if (!event.title || event.title.trim().length === 0) {
+ errors.push({
+ field: 'title',
+ message: 'Event title is required',
+ code: 'TITLE_REQUIRED'
+ });
+ }
+ if (!event.location || event.location.trim().length === 0) {
+ errors.push({
+ field: 'location',
+ message: 'Event location is required',
+ code: 'LOCATION_REQUIRED'
+ });
+ }
+ if (!event.type || event.type.trim().length === 0) {
+ errors.push({
+ field: 'type',
+ message: 'Event type is required',
+ code: 'TYPE_REQUIRED'
+ });
+ }
+ // 8. Validate title length
+ if (event.title && event.title.length > 100) {
+ errors.push({
+ field: 'title',
+ message: 'Event title cannot exceed 100 characters',
+ code: 'TITLE_TOO_LONG'
+ });
+ }
+ // 9. Validate location length
+ if (event.location && event.location.length > 200) {
+ errors.push({
+ field: 'location',
+ message: 'Event location cannot exceed 200 characters',
+ code: 'LOCATION_TOO_LONG'
+ });
+ }
+ // 10. Check for reasonable scheduling (not more than 2 years in the future)
+ const twoYearsFromNow = new Date();
+ twoYearsFromNow.setFullYear(twoYearsFromNow.getFullYear() + 2);
+ if (startTime > twoYearsFromNow) {
+ errors.push({
+ field: 'startTime',
+ message: 'Event cannot be scheduled more than 2 years in the future',
+ code: 'START_TIME_TOO_FAR'
+ });
+ }
+ // 11. Check for business hours validation (optional warning)
+ const startHour = startTime.getHours();
+ const endHour = endTime.getHours();
+ if (startHour < 6 || startHour > 23) {
+ // This is a warning, not an error - we'll add it but with a different severity
+ errors.push({
+ field: 'startTime',
+ message: 'Event starts outside typical business hours (6 AM - 11 PM)',
+ code: 'OUTSIDE_BUSINESS_HOURS'
+ });
+ }
+ return errors;
+ }
+ // Validate multiple events for conflicts and logical sequencing
+ validateEventSequence(events) {
+ const errors = [];
+ // Sort events by start time
+ const sortedEvents = events
+ .map((event, index) => ({ ...event, originalIndex: index }))
+ .sort((a, b) => new Date(a.startTime).getTime() - new Date(b.startTime).getTime());
+ // Check for overlapping events
+ for (let i = 0; i < sortedEvents.length - 1; i++) {
+ const currentEvent = sortedEvents[i];
+ const nextEvent = sortedEvents[i + 1];
+ const currentEnd = new Date(currentEvent.endTime);
+ const nextStart = new Date(nextEvent.startTime);
+ if (currentEnd > nextStart) {
+ errors.push({
+ field: 'schedule',
+ message: `Event "${currentEvent.title}" overlaps with "${nextEvent.title}"`,
+ code: 'EVENTS_OVERLAP'
+ });
+ }
+ }
+ return errors;
+ }
+ // Get user-friendly error messages
+ getErrorSummary(errors) {
+ if (errors.length === 0)
+ return '';
+ const errorMessages = errors.map(error => error.message);
+ if (errors.length === 1) {
+ return errorMessages[0];
+ }
+ return `Multiple validation errors:\n• ${errorMessages.join('\n• ')}`;
+ }
+ // Check if errors are warnings vs critical errors
+ isCriticalError(error) {
+ const warningCodes = ['OUTSIDE_BUSINESS_HOURS'];
+ return !warningCodes.includes(error.code);
+ }
+ // Separate critical errors from warnings
+ categorizeErrors(errors) {
+ const critical = [];
+ const warnings = [];
+ errors.forEach(error => {
+ if (this.isCriticalError(error)) {
+ critical.push(error);
+ }
+ else {
+ warnings.push(error);
+ }
+ });
+ return { critical, warnings };
+ }
+ // Validate time format and suggest corrections
+ validateTimeFormat(timeString) {
+ const date = new Date(timeString);
+ if (isNaN(date.getTime())) {
+ return {
+ isValid: false,
+ suggestion: 'Please use format: YYYY-MM-DDTHH:MM (e.g., 2025-07-01T14:30)'
+ };
+ }
+ return { isValid: true };
+ }
+}
+exports.default = new ScheduleValidationService();
+//# sourceMappingURL=scheduleValidationService.js.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/scheduleValidationService.js.map b/backend-old-20260125/dist/services/scheduleValidationService.js.map
new file mode 100644
index 0000000..0d07aa1
--- /dev/null
+++ b/backend-old-20260125/dist/services/scheduleValidationService.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"scheduleValidationService.js","sourceRoot":"","sources":["../../src/services/scheduleValidationService.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/unifiedDataService.d.ts b/backend-old-20260125/dist/services/unifiedDataService.d.ts
new file mode 100644
index 0000000..fb571c8
--- /dev/null
+++ b/backend-old-20260125/dist/services/unifiedDataService.d.ts
@@ -0,0 +1,30 @@
+declare class UnifiedDataService {
+ private pool;
+ constructor();
+ private toCamelCase;
+ getVips(): Promise;
+ getVipById(id: string): Promise;
+ createVip(vipData: any): Promise;
+ updateVip(id: string, vipData: any): Promise;
+ deleteVip(id: string): Promise;
+ getDrivers(): Promise;
+ getDriverById(id: string): Promise;
+ createDriver(driverData: any): Promise;
+ updateDriver(id: string, driverData: any): Promise;
+ deleteDriver(id: string): Promise;
+ getScheduleByVipId(vipId: string): Promise;
+ createScheduleEvent(vipId: string, eventData: any): Promise;
+ updateScheduleEvent(id: string, eventData: any): Promise;
+ deleteScheduleEvent(id: string): Promise;
+ getAllSchedules(): Promise>;
+ getUserByEmail(email: string): Promise;
+ getUserById(id: string): Promise;
+ createUser(userData: any): Promise;
+ updateUserRole(email: string, role: string): Promise;
+ getUserCount(): Promise;
+ getAdminSettings(): Promise;
+ updateAdminSetting(key: string, value: string): Promise;
+}
+declare const _default: UnifiedDataService;
+export default _default;
+//# sourceMappingURL=unifiedDataService.d.ts.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/unifiedDataService.d.ts.map b/backend-old-20260125/dist/services/unifiedDataService.d.ts.map
new file mode 100644
index 0000000..c55cad6
--- /dev/null
+++ b/backend-old-20260125/dist/services/unifiedDataService.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"unifiedDataService.d.ts","sourceRoot":"","sources":["../../src/services/unifiedDataService.ts"],"names":[],"mappings":"AAIA,cAAM,kBAAkB;IACtB,OAAO,CAAC,IAAI,CAAO;;IAOnB,OAAO,CAAC,WAAW;IAab,OAAO;IAwBP,UAAU,CAAC,EAAE,EAAE,MAAM;IAwBrB,SAAS,CAAC,OAAO,EAAE,GAAG;IA2CtB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG;IAkDlC,SAAS,CAAC,EAAE,EAAE,MAAM;IASpB,UAAU;IAOV,aAAa,CAAC,EAAE,EAAE,MAAM;IAQxB,YAAY,CAAC,UAAU,EAAE,GAAG;IAa5B,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG;IAcxC,YAAY,CAAC,EAAE,EAAE,MAAM;IASvB,kBAAkB,CAAC,KAAK,EAAE,MAAM;IAYhC,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG;IAajD,mBAAmB,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG;IAe9C,mBAAmB,CAAC,EAAE,EAAE,MAAM;IAQ9B,eAAe;IAuBf,cAAc,CAAC,KAAK,EAAE,MAAM;IAQ5B,WAAW,CAAC,EAAE,EAAE,MAAM;IAQtB,UAAU,CAAC,QAAQ,EAAE,GAAG;IAaxB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAW1C,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAM/B,gBAAgB;IAWhB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;CAQpD;;AAED,wBAAwC"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/unifiedDataService.js b/backend-old-20260125/dist/services/unifiedDataService.js
new file mode 100644
index 0000000..8803380
--- /dev/null
+++ b/backend-old-20260125/dist/services/unifiedDataService.js
@@ -0,0 +1,264 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const database_1 = __importDefault(require("../config/database"));
+// Simplified, unified data service that replaces the three redundant services
+class UnifiedDataService {
+ constructor() {
+ this.pool = database_1.default;
+ }
+ // Helper to convert snake_case to camelCase
+ toCamelCase(obj) {
+ if (!obj)
+ return obj;
+ if (Array.isArray(obj))
+ return obj.map(item => this.toCamelCase(item));
+ if (typeof obj !== 'object')
+ return obj;
+ return Object.keys(obj).reduce((result, key) => {
+ const camelKey = key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
+ result[camelKey] = this.toCamelCase(obj[key]);
+ return result;
+ }, {});
+ }
+ // VIP Operations
+ async getVips() {
+ const query = `
+ SELECT v.*,
+ COALESCE(
+ JSON_AGG(
+ JSON_BUILD_OBJECT(
+ 'flightNumber', f.flight_number,
+ 'airline', f.airline,
+ 'scheduledArrival', f.scheduled_arrival,
+ 'scheduledDeparture', f.scheduled_departure,
+ 'status', f.status
+ ) ORDER BY f.scheduled_arrival
+ ) FILTER (WHERE f.id IS NOT NULL),
+ '[]'
+ ) as flights
+ FROM vips v
+ LEFT JOIN flights f ON v.id = f.vip_id
+ GROUP BY v.id
+ ORDER BY v.created_at DESC`;
+ const result = await this.pool.query(query);
+ return this.toCamelCase(result.rows);
+ }
+ async getVipById(id) {
+ const query = `
+ SELECT v.*,
+ COALESCE(
+ JSON_AGG(
+ JSON_BUILD_OBJECT(
+ 'flightNumber', f.flight_number,
+ 'airline', f.airline,
+ 'scheduledArrival', f.scheduled_arrival,
+ 'scheduledDeparture', f.scheduled_departure,
+ 'status', f.status
+ ) ORDER BY f.scheduled_arrival
+ ) FILTER (WHERE f.id IS NOT NULL),
+ '[]'
+ ) as flights
+ FROM vips v
+ LEFT JOIN flights f ON v.id = f.vip_id
+ WHERE v.id = $1
+ GROUP BY v.id`;
+ const result = await this.pool.query(query, [id]);
+ return this.toCamelCase(result.rows[0]);
+ }
+ async createVip(vipData) {
+ const { name, organization, department, transportMode, flights, expectedArrival, needsAirportPickup, needsVenueTransport, notes } = vipData;
+ const client = await this.pool.connect();
+ try {
+ await client.query('BEGIN');
+ // Insert VIP
+ const vipQuery = `
+ INSERT INTO vips (name, organization, department, transport_mode, expected_arrival,
+ needs_airport_pickup, needs_venue_transport, notes)
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
+ RETURNING *`;
+ const vipResult = await client.query(vipQuery, [
+ name, organization, department || 'Office of Development', transportMode || 'flight',
+ expectedArrival, needsAirportPickup !== false, needsVenueTransport !== false, notes || ''
+ ]);
+ const vip = vipResult.rows[0];
+ // Insert flights if any
+ if (transportMode === 'flight' && flights?.length > 0) {
+ for (const flight of flights) {
+ await client.query(`INSERT INTO flights (vip_id, flight_number, airline, scheduled_arrival, scheduled_departure)
+ VALUES ($1, $2, $3, $4, $5)`, [vip.id, flight.flightNumber, flight.airline, flight.scheduledArrival, flight.scheduledDeparture]);
+ }
+ }
+ await client.query('COMMIT');
+ return this.getVipById(vip.id);
+ }
+ catch (error) {
+ await client.query('ROLLBACK');
+ throw error;
+ }
+ finally {
+ client.release();
+ }
+ }
+ async updateVip(id, vipData) {
+ const { name, organization, department, transportMode, flights, expectedArrival, needsAirportPickup, needsVenueTransport, notes } = vipData;
+ const client = await this.pool.connect();
+ try {
+ await client.query('BEGIN');
+ // Update VIP
+ const updateQuery = `
+ UPDATE vips
+ SET name = $2, organization = $3, department = $4, transport_mode = $5,
+ expected_arrival = $6, needs_airport_pickup = $7, needs_venue_transport = $8,
+ notes = $9, updated_at = NOW()
+ WHERE id = $1
+ RETURNING *`;
+ const result = await client.query(updateQuery, [
+ id, name, organization, department, transportMode,
+ expectedArrival, needsAirportPickup, needsVenueTransport, notes
+ ]);
+ if (result.rows.length === 0) {
+ await client.query('ROLLBACK');
+ return null;
+ }
+ // Update flights
+ await client.query('DELETE FROM flights WHERE vip_id = $1', [id]);
+ if (transportMode === 'flight' && flights?.length > 0) {
+ for (const flight of flights) {
+ await client.query(`INSERT INTO flights (vip_id, flight_number, airline, scheduled_arrival, scheduled_departure)
+ VALUES ($1, $2, $3, $4, $5)`, [id, flight.flightNumber, flight.airline, flight.scheduledArrival, flight.scheduledDeparture]);
+ }
+ }
+ await client.query('COMMIT');
+ return this.getVipById(id);
+ }
+ catch (error) {
+ await client.query('ROLLBACK');
+ throw error;
+ }
+ finally {
+ client.release();
+ }
+ }
+ async deleteVip(id) {
+ const result = await this.pool.query('DELETE FROM vips WHERE id = $1 RETURNING *', [id]);
+ return this.toCamelCase(result.rows[0]);
+ }
+ // Driver Operations
+ async getDrivers() {
+ const result = await this.pool.query('SELECT * FROM drivers ORDER BY name ASC');
+ return this.toCamelCase(result.rows);
+ }
+ async getDriverById(id) {
+ const result = await this.pool.query('SELECT * FROM drivers WHERE id = $1', [id]);
+ return this.toCamelCase(result.rows[0]);
+ }
+ async createDriver(driverData) {
+ const { name, email, phone, vehicleInfo, status } = driverData;
+ const result = await this.pool.query(`INSERT INTO drivers (name, email, phone, vehicle_info, status)
+ VALUES ($1, $2, $3, $4, $5)
+ RETURNING *`, [name, email, phone, vehicleInfo, status || 'available']);
+ return this.toCamelCase(result.rows[0]);
+ }
+ async updateDriver(id, driverData) {
+ const { name, email, phone, vehicleInfo, status } = driverData;
+ const result = await this.pool.query(`UPDATE drivers
+ SET name = $2, email = $3, phone = $4, vehicle_info = $5, status = $6, updated_at = NOW()
+ WHERE id = $1
+ RETURNING *`, [id, name, email, phone, vehicleInfo, status]);
+ return this.toCamelCase(result.rows[0]);
+ }
+ async deleteDriver(id) {
+ const result = await this.pool.query('DELETE FROM drivers WHERE id = $1 RETURNING *', [id]);
+ return this.toCamelCase(result.rows[0]);
+ }
+ // Schedule Operations
+ async getScheduleByVipId(vipId) {
+ const result = await this.pool.query(`SELECT se.*, d.name as driver_name
+ FROM schedule_events se
+ LEFT JOIN drivers d ON se.driver_id = d.id
+ WHERE se.vip_id = $1
+ ORDER BY se.event_time ASC`, [vipId]);
+ return this.toCamelCase(result.rows);
+ }
+ async createScheduleEvent(vipId, eventData) {
+ const { driverId, eventTime, eventType, location, notes } = eventData;
+ const result = await this.pool.query(`INSERT INTO schedule_events (vip_id, driver_id, event_time, event_type, location, notes)
+ VALUES ($1, $2, $3, $4, $5, $6)
+ RETURNING *`, [vipId, driverId, eventTime, eventType, location, notes]);
+ return this.toCamelCase(result.rows[0]);
+ }
+ async updateScheduleEvent(id, eventData) {
+ const { driverId, eventTime, eventType, location, notes, status } = eventData;
+ const result = await this.pool.query(`UPDATE schedule_events
+ SET driver_id = $2, event_time = $3, event_type = $4, location = $5,
+ notes = $6, status = $7, updated_at = NOW()
+ WHERE id = $1
+ RETURNING *`, [id, driverId, eventTime, eventType, location, notes, status]);
+ return this.toCamelCase(result.rows[0]);
+ }
+ async deleteScheduleEvent(id) {
+ const result = await this.pool.query('DELETE FROM schedule_events WHERE id = $1 RETURNING *', [id]);
+ return this.toCamelCase(result.rows[0]);
+ }
+ async getAllSchedules() {
+ const result = await this.pool.query(`SELECT se.*, d.name as driver_name, v.name as vip_name
+ FROM schedule_events se
+ LEFT JOIN drivers d ON se.driver_id = d.id
+ LEFT JOIN vips v ON se.vip_id = v.id
+ ORDER BY se.event_time ASC`);
+ // Group by VIP ID
+ const schedules = {};
+ result.rows.forEach((row) => {
+ const event = this.toCamelCase(row);
+ if (!schedules[event.vipId]) {
+ schedules[event.vipId] = [];
+ }
+ schedules[event.vipId].push(event);
+ });
+ return schedules;
+ }
+ // User Operations (simplified)
+ async getUserByEmail(email) {
+ const result = await this.pool.query('SELECT * FROM users WHERE email = $1', [email]);
+ return this.toCamelCase(result.rows[0]);
+ }
+ async getUserById(id) {
+ const result = await this.pool.query('SELECT * FROM users WHERE id = $1', [id]);
+ return this.toCamelCase(result.rows[0]);
+ }
+ async createUser(userData) {
+ const { email, name, role, department, googleId } = userData;
+ const result = await this.pool.query(`INSERT INTO users (email, name, role, department, google_id)
+ VALUES ($1, $2, $3, $4, $5)
+ RETURNING *`, [email, name, role || 'coordinator', department || 'Office of Development', googleId]);
+ return this.toCamelCase(result.rows[0]);
+ }
+ async updateUserRole(email, role) {
+ const result = await this.pool.query(`UPDATE users SET role = $2, updated_at = NOW()
+ WHERE email = $1
+ RETURNING *`, [email, role]);
+ return this.toCamelCase(result.rows[0]);
+ }
+ async getUserCount() {
+ const result = await this.pool.query('SELECT COUNT(*) FROM users');
+ return parseInt(result.rows[0].count, 10);
+ }
+ // Admin Settings (simplified)
+ async getAdminSettings() {
+ const result = await this.pool.query('SELECT key, value FROM admin_settings');
+ return result.rows.reduce((settings, row) => {
+ settings[row.key] = row.value;
+ return settings;
+ }, {});
+ }
+ async updateAdminSetting(key, value) {
+ await this.pool.query(`INSERT INTO admin_settings (key, value)
+ VALUES ($1, $2)
+ ON CONFLICT (key) DO UPDATE SET value = $2, updated_at = NOW()`, [key, value]);
+ }
+}
+exports.default = new UnifiedDataService();
+//# sourceMappingURL=unifiedDataService.js.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/services/unifiedDataService.js.map b/backend-old-20260125/dist/services/unifiedDataService.js.map
new file mode 100644
index 0000000..708f307
--- /dev/null
+++ b/backend-old-20260125/dist/services/unifiedDataService.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"unifiedDataService.js","sourceRoot":"","sources":["../../src/services/unifiedDataService.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/types/api.d.ts b/backend-old-20260125/dist/types/api.d.ts
new file mode 100644
index 0000000..7744d55
--- /dev/null
+++ b/backend-old-20260125/dist/types/api.d.ts
@@ -0,0 +1,69 @@
+export interface SuccessResponse {
+ success: true;
+ data: T;
+ message?: string;
+ timestamp: string;
+}
+export interface PaginatedResponse {
+ success: true;
+ data: T[];
+ pagination: {
+ page: number;
+ limit: number;
+ total: number;
+ totalPages: number;
+ };
+ timestamp: string;
+}
+export interface User {
+ id: string;
+ email: string;
+ name: string;
+ role: 'admin' | 'coordinator' | 'driver';
+ department?: string;
+ createdAt: Date;
+ updatedAt: Date;
+}
+export interface VIP {
+ id: string;
+ name: string;
+ email?: string;
+ phone?: string;
+ arrivalMode: 'flight' | 'driving';
+ flightNumber?: string;
+ arrivalTime?: Date;
+ departureTime?: Date;
+ notes?: string;
+ status: 'pending' | 'confirmed' | 'completed' | 'cancelled';
+ createdAt: Date;
+ updatedAt: Date;
+}
+export interface Driver {
+ id: string;
+ name: string;
+ email?: string;
+ phone: string;
+ vehicleInfo?: string;
+ status: 'available' | 'assigned' | 'unavailable';
+ createdAt: Date;
+ updatedAt: Date;
+}
+export interface ScheduleEvent {
+ id: string;
+ vipId: string;
+ driverId?: string;
+ eventType: 'pickup' | 'dropoff' | 'custom';
+ eventTime: Date;
+ location: string;
+ notes?: string;
+ status: 'scheduled' | 'in_progress' | 'completed' | 'cancelled';
+ createdAt: Date;
+ updatedAt: Date;
+}
+export interface AuthRequest extends Request {
+ user?: User;
+ requestId?: string;
+}
+export declare const successResponse: (data: T, message?: string) => SuccessResponse;
+export declare const paginatedResponse: (data: T[], page: number, limit: number, total: number) => PaginatedResponse;
+//# sourceMappingURL=api.d.ts.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/types/api.d.ts.map b/backend-old-20260125/dist/types/api.d.ts.map
new file mode 100644
index 0000000..bbe9a98
--- /dev/null
+++ b/backend-old-20260125/dist/types/api.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/types/api.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,GAAG;IACtC,OAAO,EAAE,IAAI,CAAC;IACd,IAAI,EAAE,CAAC,CAAC;IACR,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB,CAAC,CAAC,GAAG,GAAG;IACxC,OAAO,EAAE,IAAI,CAAC;IACd,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,UAAU,EAAE;QACV,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,SAAS,EAAE,MAAM,CAAC;CACnB;AAGD,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,GAAG,aAAa,GAAG,QAAQ,CAAC;IACzC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAGD,MAAM,WAAW,GAAG;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,QAAQ,GAAG,SAAS,CAAC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,IAAI,CAAC;IACnB,aAAa,CAAC,EAAE,IAAI,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,CAAC;IAC5D,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAGD,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,WAAW,GAAG,UAAU,GAAG,aAAa,CAAC;IACjD,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAGD,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;IAC3C,SAAS,EAAE,IAAI,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,WAAW,GAAG,aAAa,GAAG,WAAW,GAAG,WAAW,CAAC;IAChE,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAGD,MAAM,WAAW,WAAY,SAAQ,OAAO;IAC1C,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAGD,eAAO,MAAM,eAAe,GAAI,CAAC,EAAE,MAAM,CAAC,EAAE,UAAU,MAAM,KAAG,eAAe,CAAC,CAAC,CAK9E,CAAC;AAEH,eAAO,MAAM,iBAAiB,GAAI,CAAC,EACjC,MAAM,CAAC,EAAE,EACT,MAAM,MAAM,EACZ,OAAO,MAAM,EACb,OAAO,MAAM,KACZ,iBAAiB,CAAC,CAAC,CAUpB,CAAC"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/types/api.js b/backend-old-20260125/dist/types/api.js
new file mode 100644
index 0000000..caf261e
--- /dev/null
+++ b/backend-old-20260125/dist/types/api.js
@@ -0,0 +1,24 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.paginatedResponse = exports.successResponse = void 0;
+// Response helper functions
+const successResponse = (data, message) => ({
+ success: true,
+ data,
+ message,
+ timestamp: new Date().toISOString()
+});
+exports.successResponse = successResponse;
+const paginatedResponse = (data, page, limit, total) => ({
+ success: true,
+ data,
+ pagination: {
+ page,
+ limit,
+ total,
+ totalPages: Math.ceil(total / limit)
+ },
+ timestamp: new Date().toISOString()
+});
+exports.paginatedResponse = paginatedResponse;
+//# sourceMappingURL=api.js.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/types/api.js.map b/backend-old-20260125/dist/types/api.js.map
new file mode 100644
index 0000000..af3be91
--- /dev/null
+++ b/backend-old-20260125/dist/types/api.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/types/api.ts"],"names":[],"mappings":";;;AA8EA,4BAA4B;AACrB,MAAM,eAAe,GAAG,CAAI,IAAO,EAAE,OAAgB,EAAsB,EAAE,CAAC,CAAC;IACpF,OAAO,EAAE,IAAI;IACb,IAAI;IACJ,OAAO;IACP,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;CACpC,CAAC,CAAC;AALU,QAAA,eAAe,mBAKzB;AAEI,MAAM,iBAAiB,GAAG,CAC/B,IAAS,EACT,IAAY,EACZ,KAAa,EACb,KAAa,EACS,EAAE,CAAC,CAAC;IAC1B,OAAO,EAAE,IAAI;IACb,IAAI;IACJ,UAAU,EAAE;QACV,IAAI;QACJ,KAAK;QACL,KAAK;QACL,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;KACrC;IACD,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;CACpC,CAAC,CAAC;AAfU,QAAA,iBAAiB,qBAe3B"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/types/errors.d.ts b/backend-old-20260125/dist/types/errors.d.ts
new file mode 100644
index 0000000..b5da53b
--- /dev/null
+++ b/backend-old-20260125/dist/types/errors.d.ts
@@ -0,0 +1,34 @@
+export declare class AppError extends Error {
+ readonly statusCode: number;
+ readonly isOperational: boolean;
+ constructor(message: string, statusCode: number, isOperational?: boolean);
+}
+export declare class ValidationError extends AppError {
+ constructor(message: string);
+}
+export declare class AuthenticationError extends AppError {
+ constructor(message?: string);
+}
+export declare class AuthorizationError extends AppError {
+ constructor(message?: string);
+}
+export declare class NotFoundError extends AppError {
+ constructor(message: string);
+}
+export declare class ConflictError extends AppError {
+ constructor(message: string);
+}
+export declare class DatabaseError extends AppError {
+ constructor(message?: string);
+}
+export interface ErrorResponse {
+ success: false;
+ error: {
+ message: string;
+ code?: string;
+ details?: any;
+ };
+ timestamp: string;
+ path?: string;
+}
+//# sourceMappingURL=errors.d.ts.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/types/errors.d.ts.map b/backend-old-20260125/dist/types/errors.d.ts.map
new file mode 100644
index 0000000..7a59708
--- /dev/null
+++ b/backend-old-20260125/dist/types/errors.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/types/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,QAAS,SAAQ,KAAK;IACjC,SAAgB,UAAU,EAAE,MAAM,CAAC;IACnC,SAAgB,aAAa,EAAE,OAAO,CAAC;gBAE3B,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,UAAO;CAOtE;AAED,qBAAa,eAAgB,SAAQ,QAAQ;gBAC/B,OAAO,EAAE,MAAM;CAG5B;AAED,qBAAa,mBAAoB,SAAQ,QAAQ;gBACnC,OAAO,SAA0B;CAG9C;AAED,qBAAa,kBAAmB,SAAQ,QAAQ;gBAClC,OAAO,SAA6B;CAGjD;AAED,qBAAa,aAAc,SAAQ,QAAQ;gBAC7B,OAAO,EAAE,MAAM;CAG5B;AAED,qBAAa,aAAc,SAAQ,QAAQ;gBAC7B,OAAO,EAAE,MAAM;CAG5B;AAED,qBAAa,aAAc,SAAQ,QAAQ;gBAC7B,OAAO,SAA8B;CAGlD;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,KAAK,CAAC;IACf,KAAK,EAAE;QACL,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,GAAG,CAAC;KACf,CAAC;IACF,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/types/errors.js b/backend-old-20260125/dist/types/errors.js
new file mode 100644
index 0000000..bfd58df
--- /dev/null
+++ b/backend-old-20260125/dist/types/errors.js
@@ -0,0 +1,49 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.DatabaseError = exports.ConflictError = exports.NotFoundError = exports.AuthorizationError = exports.AuthenticationError = exports.ValidationError = exports.AppError = void 0;
+class AppError extends Error {
+ constructor(message, statusCode, isOperational = true) {
+ super(message);
+ this.statusCode = statusCode;
+ this.isOperational = isOperational;
+ Error.captureStackTrace(this, this.constructor);
+ }
+}
+exports.AppError = AppError;
+class ValidationError extends AppError {
+ constructor(message) {
+ super(message, 400, true);
+ }
+}
+exports.ValidationError = ValidationError;
+class AuthenticationError extends AppError {
+ constructor(message = 'Authentication failed') {
+ super(message, 401, true);
+ }
+}
+exports.AuthenticationError = AuthenticationError;
+class AuthorizationError extends AppError {
+ constructor(message = 'Insufficient permissions') {
+ super(message, 403, true);
+ }
+}
+exports.AuthorizationError = AuthorizationError;
+class NotFoundError extends AppError {
+ constructor(message) {
+ super(message, 404, true);
+ }
+}
+exports.NotFoundError = NotFoundError;
+class ConflictError extends AppError {
+ constructor(message) {
+ super(message, 409, true);
+ }
+}
+exports.ConflictError = ConflictError;
+class DatabaseError extends AppError {
+ constructor(message = 'Database operation failed') {
+ super(message, 500, false);
+ }
+}
+exports.DatabaseError = DatabaseError;
+//# sourceMappingURL=errors.js.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/types/errors.js.map b/backend-old-20260125/dist/types/errors.js.map
new file mode 100644
index 0000000..8e8ca7a
--- /dev/null
+++ b/backend-old-20260125/dist/types/errors.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/types/errors.ts"],"names":[],"mappings":";;;AAAA,MAAa,QAAS,SAAQ,KAAK;IAIjC,YAAY,OAAe,EAAE,UAAkB,EAAE,aAAa,GAAG,IAAI;QACnE,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QAEnC,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAClD,CAAC;CACF;AAXD,4BAWC;AAED,MAAa,eAAgB,SAAQ,QAAQ;IAC3C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;IAC5B,CAAC;CACF;AAJD,0CAIC;AAED,MAAa,mBAAoB,SAAQ,QAAQ;IAC/C,YAAY,OAAO,GAAG,uBAAuB;QAC3C,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;IAC5B,CAAC;CACF;AAJD,kDAIC;AAED,MAAa,kBAAmB,SAAQ,QAAQ;IAC9C,YAAY,OAAO,GAAG,0BAA0B;QAC9C,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;IAC5B,CAAC;CACF;AAJD,gDAIC;AAED,MAAa,aAAc,SAAQ,QAAQ;IACzC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;IAC5B,CAAC;CACF;AAJD,sCAIC;AAED,MAAa,aAAc,SAAQ,QAAQ;IACzC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;IAC5B,CAAC;CACF;AAJD,sCAIC;AAED,MAAa,aAAc,SAAQ,QAAQ;IACzC,YAAY,OAAO,GAAG,2BAA2B;QAC/C,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;IAC7B,CAAC;CACF;AAJD,sCAIC"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/types/schemas.d.ts b/backend-old-20260125/dist/types/schemas.d.ts
new file mode 100644
index 0000000..fb979d0
--- /dev/null
+++ b/backend-old-20260125/dist/types/schemas.d.ts
@@ -0,0 +1,364 @@
+import { z } from 'zod';
+export declare const vipFlightSchema: z.ZodObject<{
+ flightNumber: z.ZodString;
+ airline: z.ZodOptional;
+ scheduledArrival: z.ZodUnion<[z.ZodString, z.ZodDate]>;
+ scheduledDeparture: z.ZodOptional>;
+ status: z.ZodOptional>;
+}, "strip", z.ZodTypeAny, {
+ flightNumber: string;
+ scheduledArrival: string | Date;
+ status?: "scheduled" | "cancelled" | "delayed" | "arrived" | undefined;
+ airline?: string | undefined;
+ scheduledDeparture?: string | Date | undefined;
+}, {
+ flightNumber: string;
+ scheduledArrival: string | Date;
+ status?: "scheduled" | "cancelled" | "delayed" | "arrived" | undefined;
+ airline?: string | undefined;
+ scheduledDeparture?: string | Date | undefined;
+}>;
+export declare const createVipSchema: z.ZodEffects;
+ department: z.ZodDefault>;
+ transportMode: z.ZodDefault>;
+ flights: z.ZodOptional;
+ scheduledArrival: z.ZodUnion<[z.ZodString, z.ZodDate]>;
+ scheduledDeparture: z.ZodOptional>;
+ status: z.ZodOptional>;
+ }, "strip", z.ZodTypeAny, {
+ flightNumber: string;
+ scheduledArrival: string | Date;
+ status?: "scheduled" | "cancelled" | "delayed" | "arrived" | undefined;
+ airline?: string | undefined;
+ scheduledDeparture?: string | Date | undefined;
+ }, {
+ flightNumber: string;
+ scheduledArrival: string | Date;
+ status?: "scheduled" | "cancelled" | "delayed" | "arrived" | undefined;
+ airline?: string | undefined;
+ scheduledDeparture?: string | Date | undefined;
+ }>, "many">>;
+ expectedArrival: z.ZodOptional>;
+ needsAirportPickup: z.ZodDefault;
+ needsVenueTransport: z.ZodDefault;
+ notes: z.ZodOptional;
+}, "strip", z.ZodTypeAny, {
+ name: string;
+ department: "Office of Development" | "Admin";
+ transportMode: "flight" | "self-driving";
+ needsAirportPickup: boolean;
+ needsVenueTransport: boolean;
+ organization?: string | undefined;
+ flights?: {
+ flightNumber: string;
+ scheduledArrival: string | Date;
+ status?: "scheduled" | "cancelled" | "delayed" | "arrived" | undefined;
+ airline?: string | undefined;
+ scheduledDeparture?: string | Date | undefined;
+ }[] | undefined;
+ expectedArrival?: string | Date | undefined;
+ notes?: string | undefined;
+}, {
+ name: string;
+ organization?: string | undefined;
+ department?: "Office of Development" | "Admin" | undefined;
+ transportMode?: "flight" | "self-driving" | undefined;
+ flights?: {
+ flightNumber: string;
+ scheduledArrival: string | Date;
+ status?: "scheduled" | "cancelled" | "delayed" | "arrived" | undefined;
+ airline?: string | undefined;
+ scheduledDeparture?: string | Date | undefined;
+ }[] | undefined;
+ expectedArrival?: string | Date | undefined;
+ needsAirportPickup?: boolean | undefined;
+ needsVenueTransport?: boolean | undefined;
+ notes?: string | undefined;
+}>, {
+ name: string;
+ department: "Office of Development" | "Admin";
+ transportMode: "flight" | "self-driving";
+ needsAirportPickup: boolean;
+ needsVenueTransport: boolean;
+ organization?: string | undefined;
+ flights?: {
+ flightNumber: string;
+ scheduledArrival: string | Date;
+ status?: "scheduled" | "cancelled" | "delayed" | "arrived" | undefined;
+ airline?: string | undefined;
+ scheduledDeparture?: string | Date | undefined;
+ }[] | undefined;
+ expectedArrival?: string | Date | undefined;
+ notes?: string | undefined;
+}, {
+ name: string;
+ organization?: string | undefined;
+ department?: "Office of Development" | "Admin" | undefined;
+ transportMode?: "flight" | "self-driving" | undefined;
+ flights?: {
+ flightNumber: string;
+ scheduledArrival: string | Date;
+ status?: "scheduled" | "cancelled" | "delayed" | "arrived" | undefined;
+ airline?: string | undefined;
+ scheduledDeparture?: string | Date | undefined;
+ }[] | undefined;
+ expectedArrival?: string | Date | undefined;
+ needsAirportPickup?: boolean | undefined;
+ needsVenueTransport?: boolean | undefined;
+ notes?: string | undefined;
+}>;
+export declare const updateVipSchema: z.ZodObject<{
+ name: z.ZodOptional;
+ organization: z.ZodOptional;
+ department: z.ZodOptional>;
+ transportMode: z.ZodOptional>;
+ flights: z.ZodOptional;
+ scheduledArrival: z.ZodUnion<[z.ZodString, z.ZodDate]>;
+ scheduledDeparture: z.ZodOptional>;
+ status: z.ZodOptional>;
+ }, "strip", z.ZodTypeAny, {
+ flightNumber: string;
+ scheduledArrival: string | Date;
+ status?: "scheduled" | "cancelled" | "delayed" | "arrived" | undefined;
+ airline?: string | undefined;
+ scheduledDeparture?: string | Date | undefined;
+ }, {
+ flightNumber: string;
+ scheduledArrival: string | Date;
+ status?: "scheduled" | "cancelled" | "delayed" | "arrived" | undefined;
+ airline?: string | undefined;
+ scheduledDeparture?: string | Date | undefined;
+ }>, "many">>;
+ expectedArrival: z.ZodOptional>;
+ needsAirportPickup: z.ZodOptional;
+ needsVenueTransport: z.ZodOptional;
+ notes: z.ZodOptional;
+}, "strip", z.ZodTypeAny, {
+ name?: string | undefined;
+ organization?: string | undefined;
+ department?: "Office of Development" | "Admin" | undefined;
+ transportMode?: "flight" | "self-driving" | undefined;
+ flights?: {
+ flightNumber: string;
+ scheduledArrival: string | Date;
+ status?: "scheduled" | "cancelled" | "delayed" | "arrived" | undefined;
+ airline?: string | undefined;
+ scheduledDeparture?: string | Date | undefined;
+ }[] | undefined;
+ expectedArrival?: string | Date | undefined;
+ needsAirportPickup?: boolean | undefined;
+ needsVenueTransport?: boolean | undefined;
+ notes?: string | undefined;
+}, {
+ name?: string | undefined;
+ organization?: string | undefined;
+ department?: "Office of Development" | "Admin" | undefined;
+ transportMode?: "flight" | "self-driving" | undefined;
+ flights?: {
+ flightNumber: string;
+ scheduledArrival: string | Date;
+ status?: "scheduled" | "cancelled" | "delayed" | "arrived" | undefined;
+ airline?: string | undefined;
+ scheduledDeparture?: string | Date | undefined;
+ }[] | undefined;
+ expectedArrival?: string | Date | undefined;
+ needsAirportPickup?: boolean | undefined;
+ needsVenueTransport?: boolean | undefined;
+ notes?: string | undefined;
+}>;
+export declare const createDriverSchema: z.ZodObject<{
+ name: z.ZodString;
+ email: z.ZodOptional;
+ phone: z.ZodString;
+ vehicleInfo: z.ZodOptional;
+ status: z.ZodDefault>;
+}, "strip", z.ZodTypeAny, {
+ name: string;
+ phone: string;
+ status: "available" | "assigned" | "unavailable";
+ email?: string | undefined;
+ vehicleInfo?: string | undefined;
+}, {
+ name: string;
+ phone: string;
+ email?: string | undefined;
+ vehicleInfo?: string | undefined;
+ status?: "available" | "assigned" | "unavailable" | undefined;
+}>;
+export declare const updateDriverSchema: z.ZodObject<{
+ name: z.ZodOptional;
+ email: z.ZodOptional>;
+ phone: z.ZodOptional;
+ vehicleInfo: z.ZodOptional>;
+ status: z.ZodOptional>>;
+}, "strip", z.ZodTypeAny, {
+ name?: string | undefined;
+ email?: string | undefined;
+ phone?: string | undefined;
+ vehicleInfo?: string | undefined;
+ status?: "available" | "assigned" | "unavailable" | undefined;
+}, {
+ name?: string | undefined;
+ email?: string | undefined;
+ phone?: string | undefined;
+ vehicleInfo?: string | undefined;
+ status?: "available" | "assigned" | "unavailable" | undefined;
+}>;
+export declare const createScheduleEventSchema: z.ZodObject<{
+ vipId: z.ZodString;
+ driverId: z.ZodOptional;
+ eventType: z.ZodEnum<["pickup", "dropoff", "custom"]>;
+ eventTime: z.ZodUnion<[z.ZodString, z.ZodDate]>;
+ location: z.ZodString;
+ notes: z.ZodOptional;
+ status: z.ZodDefault>;
+}, "strip", z.ZodTypeAny, {
+ status: "scheduled" | "in_progress" | "completed" | "cancelled";
+ eventTime: string | Date;
+ eventType: "custom" | "pickup" | "dropoff";
+ location: string;
+ vipId: string;
+ notes?: string | undefined;
+ driverId?: string | undefined;
+}, {
+ eventTime: string | Date;
+ eventType: "custom" | "pickup" | "dropoff";
+ location: string;
+ vipId: string;
+ notes?: string | undefined;
+ status?: "scheduled" | "in_progress" | "completed" | "cancelled" | undefined;
+ driverId?: string | undefined;
+}>;
+export declare const updateScheduleEventSchema: z.ZodObject<{
+ vipId: z.ZodOptional;
+ driverId: z.ZodOptional>;
+ eventType: z.ZodOptional>;
+ eventTime: z.ZodOptional>;
+ location: z.ZodOptional;
+ notes: z.ZodOptional>;
+ status: z.ZodOptional>>;
+}, "strip", z.ZodTypeAny, {
+ notes?: string | undefined;
+ status?: "scheduled" | "in_progress" | "completed" | "cancelled" | undefined;
+ driverId?: string | undefined;
+ eventTime?: string | Date | undefined;
+ eventType?: "custom" | "pickup" | "dropoff" | undefined;
+ location?: string | undefined;
+ vipId?: string | undefined;
+}, {
+ notes?: string | undefined;
+ status?: "scheduled" | "in_progress" | "completed" | "cancelled" | undefined;
+ driverId?: string | undefined;
+ eventTime?: string | Date | undefined;
+ eventType?: "custom" | "pickup" | "dropoff" | undefined;
+ location?: string | undefined;
+ vipId?: string | undefined;
+}>;
+export declare const createUserSchema: z.ZodObject<{
+ email: z.ZodString;
+ name: z.ZodString;
+ role: z.ZodEnum<["admin", "coordinator", "driver"]>;
+ department: z.ZodOptional;
+ password: z.ZodOptional;
+}, "strip", z.ZodTypeAny, {
+ name: string;
+ email: string;
+ role: "coordinator" | "admin" | "driver";
+ department?: string | undefined;
+ password?: string | undefined;
+}, {
+ name: string;
+ email: string;
+ role: "coordinator" | "admin" | "driver";
+ department?: string | undefined;
+ password?: string | undefined;
+}>;
+export declare const updateUserSchema: z.ZodObject<{
+ email: z.ZodOptional;
+ name: z.ZodOptional;
+ role: z.ZodOptional>;
+ department: z.ZodOptional>;
+ password: z.ZodOptional>;
+}, "strip", z.ZodTypeAny, {
+ name?: string | undefined;
+ department?: string | undefined;
+ email?: string | undefined;
+ role?: "coordinator" | "admin" | "driver" | undefined;
+ password?: string | undefined;
+}, {
+ name?: string | undefined;
+ department?: string | undefined;
+ email?: string | undefined;
+ role?: "coordinator" | "admin" | "driver" | undefined;
+ password?: string | undefined;
+}>;
+export declare const updateAdminSettingsSchema: z.ZodObject<{
+ key: z.ZodString;
+ value: z.ZodString;
+ description: z.ZodOptional;
+}, "strip", z.ZodTypeAny, {
+ value: string;
+ key: string;
+ description?: string | undefined;
+}, {
+ value: string;
+ key: string;
+ description?: string | undefined;
+}>;
+export declare const loginSchema: z.ZodObject<{
+ email: z.ZodString;
+ password: z.ZodString;
+}, "strip", z.ZodTypeAny, {
+ email: string;
+ password: string;
+}, {
+ email: string;
+ password: string;
+}>;
+export declare const googleAuthCallbackSchema: z.ZodObject<{
+ code: z.ZodString;
+}, "strip", z.ZodTypeAny, {
+ code: string;
+}, {
+ code: string;
+}>;
+export declare const paginationSchema: z.ZodObject<{
+ page: z.ZodDefault>;
+ limit: z.ZodDefault>;
+ sortBy: z.ZodOptional;
+ sortOrder: z.ZodDefault>;
+}, "strip", z.ZodTypeAny, {
+ page: number;
+ limit: number;
+ sortOrder: "asc" | "desc";
+ sortBy?: string | undefined;
+}, {
+ page?: string | undefined;
+ limit?: string | undefined;
+ sortBy?: string | undefined;
+ sortOrder?: "asc" | "desc" | undefined;
+}>;
+export declare const dateRangeSchema: z.ZodObject<{
+ startDate: z.ZodOptional;
+ endDate: z.ZodOptional;
+}, "strip", z.ZodTypeAny, {
+ startDate?: string | undefined;
+ endDate?: string | undefined;
+}, {
+ startDate?: string | undefined;
+ endDate?: string | undefined;
+}>;
+export declare const idParamSchema: z.ZodObject<{
+ id: z.ZodString;
+}, "strip", z.ZodTypeAny, {
+ id: string;
+}, {
+ id: string;
+}>;
+//# sourceMappingURL=schemas.d.ts.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/types/schemas.d.ts.map b/backend-old-20260125/dist/types/schemas.d.ts.map
new file mode 100644
index 0000000..b585c0e
--- /dev/null
+++ b/backend-old-20260125/dist/types/schemas.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/types/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAQxB,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;EAM1B,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuB3B,CAAC;AAEF,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAU1B,CAAC;AAGH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;EAM7B,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;EAA+B,CAAC;AAG/D,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;EAQpC,CAAC;AAEH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;EAAsC,CAAC;AAG7E,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;EAM3B,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;EAA6B,CAAC;AAG3D,eAAO,MAAM,yBAAyB;;;;;;;;;;;;EAIpC,CAAC;AAGH,eAAO,MAAM,WAAW;;;;;;;;;EAGtB,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;;;EAEnC,CAAC;AAGH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;EAK3B,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;;;;;EAG1B,CAAC;AAGH,eAAO,MAAM,aAAa;;;;;;EAExB,CAAC"}
\ No newline at end of file
diff --git a/backend-old-20260125/dist/types/schemas.js b/backend-old-20260125/dist/types/schemas.js
new file mode 100644
index 0000000..bf5c2d9
--- /dev/null
+++ b/backend-old-20260125/dist/types/schemas.js
@@ -0,0 +1,107 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.idParamSchema = exports.dateRangeSchema = exports.paginationSchema = exports.googleAuthCallbackSchema = exports.loginSchema = exports.updateAdminSettingsSchema = exports.updateUserSchema = exports.createUserSchema = exports.updateScheduleEventSchema = exports.createScheduleEventSchema = exports.updateDriverSchema = exports.createDriverSchema = exports.updateVipSchema = exports.createVipSchema = exports.vipFlightSchema = void 0;
+const zod_1 = require("zod");
+// Common schemas
+const phoneRegex = /^[\d\s\-\+\(\)]+$/;
+const emailSchema = zod_1.z.string().email().optional();
+const phoneSchema = zod_1.z.string().regex(phoneRegex, 'Invalid phone number format').optional();
+// VIP schemas
+exports.vipFlightSchema = zod_1.z.object({
+ flightNumber: zod_1.z.string().min(1, 'Flight number is required'),
+ airline: zod_1.z.string().optional(),
+ scheduledArrival: zod_1.z.string().datetime().or(zod_1.z.date()),
+ scheduledDeparture: zod_1.z.string().datetime().or(zod_1.z.date()).optional(),
+ status: zod_1.z.enum(['scheduled', 'delayed', 'cancelled', 'arrived']).optional()
+});
+exports.createVipSchema = zod_1.z.object({
+ name: zod_1.z.string().min(1, 'Name is required').max(100),
+ organization: zod_1.z.string().max(100).optional(),
+ department: zod_1.z.enum(['Office of Development', 'Admin']).default('Office of Development'),
+ transportMode: zod_1.z.enum(['flight', 'self-driving']).default('flight'),
+ flights: zod_1.z.array(exports.vipFlightSchema).optional(),
+ expectedArrival: zod_1.z.string().datetime().or(zod_1.z.date()).optional(),
+ needsAirportPickup: zod_1.z.boolean().default(true),
+ needsVenueTransport: zod_1.z.boolean().default(true),
+ notes: zod_1.z.string().max(500).optional()
+}).refine((data) => {
+ if (data.transportMode === 'flight' && (!data.flights || data.flights.length === 0)) {
+ return false;
+ }
+ if (data.transportMode === 'self-driving' && !data.expectedArrival) {
+ return false;
+ }
+ return true;
+}, {
+ message: 'Flight mode requires at least one flight, self-driving requires expected arrival'
+});
+exports.updateVipSchema = zod_1.z.object({
+ name: zod_1.z.string().min(1, 'Name is required').max(100).optional(),
+ organization: zod_1.z.string().max(100).optional(),
+ department: zod_1.z.enum(['Office of Development', 'Admin']).optional(),
+ transportMode: zod_1.z.enum(['flight', 'self-driving']).optional(),
+ flights: zod_1.z.array(exports.vipFlightSchema).optional(),
+ expectedArrival: zod_1.z.string().datetime().or(zod_1.z.date()).optional(),
+ needsAirportPickup: zod_1.z.boolean().optional(),
+ needsVenueTransport: zod_1.z.boolean().optional(),
+ notes: zod_1.z.string().max(500).optional()
+});
+// Driver schemas
+exports.createDriverSchema = zod_1.z.object({
+ name: zod_1.z.string().min(1, 'Name is required').max(100),
+ email: emailSchema,
+ phone: zod_1.z.string().regex(phoneRegex, 'Invalid phone number format'),
+ vehicleInfo: zod_1.z.string().max(200).optional(),
+ status: zod_1.z.enum(['available', 'assigned', 'unavailable']).default('available')
+});
+exports.updateDriverSchema = exports.createDriverSchema.partial();
+// Schedule Event schemas
+exports.createScheduleEventSchema = zod_1.z.object({
+ vipId: zod_1.z.string().uuid('Invalid VIP ID'),
+ driverId: zod_1.z.string().uuid('Invalid driver ID').optional(),
+ eventType: zod_1.z.enum(['pickup', 'dropoff', 'custom']),
+ eventTime: zod_1.z.string().datetime().or(zod_1.z.date()),
+ location: zod_1.z.string().min(1, 'Location is required').max(200),
+ notes: zod_1.z.string().max(500).optional(),
+ status: zod_1.z.enum(['scheduled', 'in_progress', 'completed', 'cancelled']).default('scheduled')
+});
+exports.updateScheduleEventSchema = exports.createScheduleEventSchema.partial();
+// User schemas
+exports.createUserSchema = zod_1.z.object({
+ email: zod_1.z.string().email('Invalid email address'),
+ name: zod_1.z.string().min(1, 'Name is required').max(100),
+ role: zod_1.z.enum(['admin', 'coordinator', 'driver']),
+ department: zod_1.z.string().max(100).optional(),
+ password: zod_1.z.string().min(8, 'Password must be at least 8 characters').optional()
+});
+exports.updateUserSchema = exports.createUserSchema.partial();
+// Admin settings schemas
+exports.updateAdminSettingsSchema = zod_1.z.object({
+ key: zod_1.z.string().min(1, 'Key is required'),
+ value: zod_1.z.string(),
+ description: zod_1.z.string().optional()
+});
+// Auth schemas
+exports.loginSchema = zod_1.z.object({
+ email: zod_1.z.string().email('Invalid email address'),
+ password: zod_1.z.string().min(1, 'Password is required')
+});
+exports.googleAuthCallbackSchema = zod_1.z.object({
+ code: zod_1.z.string().min(1, 'Authorization code is required')
+});
+// Query parameter schemas
+exports.paginationSchema = zod_1.z.object({
+ page: zod_1.z.string().regex(/^\d+$/).transform(Number).default('1'),
+ limit: zod_1.z.string().regex(/^\d+$/).transform(Number).default('20'),
+ sortBy: zod_1.z.string().optional(),
+ sortOrder: zod_1.z.enum(['asc', 'desc']).default('asc')
+});
+exports.dateRangeSchema = zod_1.z.object({
+ startDate: zod_1.z.string().datetime().optional(),
+ endDate: zod_1.z.string().datetime().optional()
+});
+// Route parameter schemas
+exports.idParamSchema = zod_1.z.object({
+ id: zod_1.z.string().min(1, 'ID is required')
+});
+//# sourceMappingURL=schemas.js.map
\ No newline at end of file
diff --git a/backend-old-20260125/dist/types/schemas.js.map b/backend-old-20260125/dist/types/schemas.js.map
new file mode 100644
index 0000000..c6316ea
--- /dev/null
+++ b/backend-old-20260125/dist/types/schemas.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../src/types/schemas.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/backend/jest.config.js b/backend-old-20260125/jest.config.js
similarity index 100%
rename from backend/jest.config.js
rename to backend-old-20260125/jest.config.js
diff --git a/backend-old-20260125/package-lock.json b/backend-old-20260125/package-lock.json
new file mode 100644
index 0000000..d6048ff
--- /dev/null
+++ b/backend-old-20260125/package-lock.json
@@ -0,0 +1,4662 @@
+{
+ "name": "vip-coordinator-backend",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "vip-coordinator-backend",
+ "version": "1.0.0",
+ "license": "ISC",
+ "dependencies": {
+ "auth0": "^5.2.0",
+ "cors": "^2.8.5",
+ "dotenv": "^16.3.1",
+ "express": "^4.18.2",
+ "express-jwt": "^8.5.1",
+ "express-openid-connect": "^2.19.4",
+ "jsonwebtoken": "^9.0.2",
+ "jwks-rsa": "^3.2.2",
+ "pg": "^8.11.3",
+ "redis": "^4.6.8",
+ "uuid": "^9.0.0"
+ },
+ "devDependencies": {
+ "@types/cors": "^2.8.13",
+ "@types/express": "^4.17.17",
+ "@types/jsonwebtoken": "^9.0.2",
+ "@types/node": "^20.5.0",
+ "@types/pg": "^8.10.2",
+ "@types/uuid": "^9.0.2",
+ "ts-node": "^10.9.1",
+ "ts-node-dev": "^2.0.0",
+ "tsx": "^4.7.0",
+ "typescript": "^5.6.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "0.3.9"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.25.8",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.8.tgz",
+ "integrity": "sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.25.8",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.8.tgz",
+ "integrity": "sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.25.8",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.8.tgz",
+ "integrity": "sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.25.8",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.8.tgz",
+ "integrity": "sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.25.8",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.8.tgz",
+ "integrity": "sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.25.8",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.8.tgz",
+ "integrity": "sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.25.8",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.8.tgz",
+ "integrity": "sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.25.8",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.8.tgz",
+ "integrity": "sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.25.8",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.8.tgz",
+ "integrity": "sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.25.8",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.8.tgz",
+ "integrity": "sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.25.8",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.8.tgz",
+ "integrity": "sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.25.8",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.8.tgz",
+ "integrity": "sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.25.8",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.8.tgz",
+ "integrity": "sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.25.8",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.8.tgz",
+ "integrity": "sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.25.8",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.8.tgz",
+ "integrity": "sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.25.8",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.8.tgz",
+ "integrity": "sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.25.8",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.8.tgz",
+ "integrity": "sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.25.8",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.8.tgz",
+ "integrity": "sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.25.8",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.8.tgz",
+ "integrity": "sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.25.8",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.8.tgz",
+ "integrity": "sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.25.8",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.8.tgz",
+ "integrity": "sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openharmony-arm64": {
+ "version": "0.25.8",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.8.tgz",
+ "integrity": "sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.25.8",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.8.tgz",
+ "integrity": "sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.25.8",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.8.tgz",
+ "integrity": "sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.25.8",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.8.tgz",
+ "integrity": "sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.25.8",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.8.tgz",
+ "integrity": "sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@hapi/hoek": {
+ "version": "9.3.0",
+ "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz",
+ "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@hapi/topo": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz",
+ "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@hapi/hoek": "^9.0.0"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz",
+ "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==",
+ "dev": 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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.0.3",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ },
+ "node_modules/@panva/asn1.js": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@panva/asn1.js/-/asn1.js-1.0.0.tgz",
+ "integrity": "sha512-UdkG3mLEqXgnlKsWanWcgb6dOjUzJ+XC5f+aWw30qrtjxeNUSfKX1cd5FBzOaXQumoe9nIqeZUvrRJS03HCCtw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/@redis/bloom": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz",
+ "integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@redis/client": "^1.0.0"
+ }
+ },
+ "node_modules/@redis/client": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.6.1.tgz",
+ "integrity": "sha512-/KCsg3xSlR+nCK8/8ZYSknYxvXHwubJrU82F3Lm1Fp6789VQ0/3RJKfsmRXjqfaTA++23CvC3hqmqe/2GEt6Kw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "cluster-key-slot": "1.1.2",
+ "generic-pool": "3.9.0",
+ "yallist": "4.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@redis/graph": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.1.tgz",
+ "integrity": "sha512-FEMTcTHZozZciLRl6GiiIB4zGm5z5F3F6a6FZCyrfxdKOhFlGkiAqlexWMBzCi4DcRoyiOsuLfW+cjlGWyExOw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@redis/client": "^1.0.0"
+ }
+ },
+ "node_modules/@redis/json": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.7.tgz",
+ "integrity": "sha512-6UyXfjVaTBTJtKNG4/9Z8PSpKE6XgSyEb8iwaqDcy+uKrd/DGYHTWkUdnQDyzm727V7p21WUMhsqz5oy65kPcQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@redis/client": "^1.0.0"
+ }
+ },
+ "node_modules/@redis/search": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.2.0.tgz",
+ "integrity": "sha512-tYoDBbtqOVigEDMAcTGsRlMycIIjwMCgD8eR2t0NANeQmgK/lvxNAvYyb6bZDD4frHRhIHkJu2TBRvB0ERkOmw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@redis/client": "^1.0.0"
+ }
+ },
+ "node_modules/@redis/time-series": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.1.0.tgz",
+ "integrity": "sha512-c1Q99M5ljsIuc4YdaCwfUEXsofakb9c8+Zse2qxTadu8TalLXuAESzLvFAvNVbkmSlvlzIQOLpBCmWI9wTOt+g==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@redis/client": "^1.0.0"
+ }
+ },
+ "node_modules/@sideway/address": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz",
+ "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@hapi/hoek": "^9.0.0"
+ }
+ },
+ "node_modules/@sideway/formula": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz",
+ "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@sideway/pinpoint": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz",
+ "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@sindresorhus/is": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
+ "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/is?sponsor=1"
+ }
+ },
+ "node_modules/@szmarczak/http-timer": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz",
+ "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==",
+ "license": "MIT",
+ "dependencies": {
+ "defer-to-connect": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "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==",
+ "dev": 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==",
+ "dev": 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==",
+ "dev": 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==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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/cacheable-request": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz",
+ "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/http-cache-semantics": "*",
+ "@types/keyv": "^3.1.4",
+ "@types/node": "*",
+ "@types/responselike": "^1.0.0"
+ }
+ },
+ "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/cors": {
+ "version": "2.8.19",
+ "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz",
+ "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/express": {
+ "version": "4.17.23",
+ "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.23.tgz",
+ "integrity": "sha512-Crp6WY9aTYP3qPi2wGDo9iUe/rceX01UMhnF1jmwDcKCFM6cx7YhGP/Mpr3y9AASpfHixIG0E6azCcL5OcDHsQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/body-parser": "*",
+ "@types/express-serve-static-core": "^4.17.33",
+ "@types/qs": "*",
+ "@types/serve-static": "*"
+ }
+ },
+ "node_modules/@types/express-serve-static-core": {
+ "version": "4.19.6",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz",
+ "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "@types/qs": "*",
+ "@types/range-parser": "*",
+ "@types/send": "*"
+ }
+ },
+ "node_modules/@types/http-cache-semantics": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz",
+ "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==",
+ "license": "MIT"
+ },
+ "node_modules/@types/http-errors": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz",
+ "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/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==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/ms": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/keyv": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz",
+ "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "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==",
+ "license": "MIT"
+ },
+ "node_modules/@types/node": {
+ "version": "20.19.9",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.9.tgz",
+ "integrity": "sha512-cuVNgarYWZqxRJDQHEB58GEONhOK79QVR/qYx4S7kcUObQvUwvFnYxJuuHUKm2aieN9X3yZB4LZsuYNU1Qphsw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "undici-types": "~6.21.0"
+ }
+ },
+ "node_modules/@types/pg": {
+ "version": "8.15.4",
+ "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.15.4.tgz",
+ "integrity": "sha512-I6UNVBAoYbvuWkkU3oosC8yxqH21f4/Jc4DK71JLG3dT2mdlGe1z+ep/LQGXaKaOgcvUrsQoPRqfgtMcvZiJhg==",
+ "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/responselike": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz",
+ "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "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/strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/strip-json-comments": {
+ "version": "0.0.30",
+ "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz",
+ "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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/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/acorn": {
+ "version": "8.15.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
+ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-walk": {
+ "version": "8.3.4",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
+ "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "acorn": "^8.11.0"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/aggregate-error": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+ "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
+ "license": "MIT",
+ "dependencies": {
+ "clean-stack": "^2.0.0",
+ "indent-string": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/arg": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
+ "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/array-buffer-byte-length": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz",
+ "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "is-array-buffer": "^3.0.5"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
+ "license": "MIT"
+ },
+ "node_modules/array.prototype.reduce": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.8.tgz",
+ "integrity": "sha512-DwuEqgXFBwbmZSRqt3BpQigWNUoqw9Ml2dTWdF3B2zQlQX4OeUE0zyuzX0fX0IbTvjdkZbcBTU3idgpO78qkTw==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.9",
+ "es-array-method-boxes-properly": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "is-string": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/arraybuffer.prototype.slice": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz",
+ "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==",
+ "license": "MIT",
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.1",
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "is-array-buffer": "^3.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/async-function": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz",
+ "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/auth0": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/auth0/-/auth0-5.2.0.tgz",
+ "integrity": "sha512-eRtzyldEhXC1g9quWI8daG/j2OcXFsjgkT+zi3gqpe3SOwVNkWyvzaDAHAYWD2Z1ARTNXxezoXJiWNxwfHRMhw==",
+ "license": "MIT",
+ "dependencies": {
+ "auth0-legacy": "npm:auth0@^4.27.0",
+ "jose": "^4.13.2",
+ "uuid": "^11.1.0"
+ },
+ "engines": {
+ "node": "^20.19.0 || ^22.12.0 || ^24.0.0"
+ }
+ },
+ "node_modules/auth0-legacy": {
+ "name": "auth0",
+ "version": "4.37.0",
+ "resolved": "https://registry.npmjs.org/auth0/-/auth0-4.37.0.tgz",
+ "integrity": "sha512-+TqJRxh4QvbD4TQIYx1ak2vanykQkG/nIZLuR6o8LoQj425gjVG3tFuUbbOeh/nCpP1rnvU0CCV1ChZHYXLU/A==",
+ "license": "MIT",
+ "dependencies": {
+ "jose": "^4.13.2",
+ "undici-types": "^6.15.0",
+ "uuid": "^9.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/auth0/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/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/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/base64url": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz",
+ "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "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/body-parser": {
+ "version": "1.20.3",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
+ "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "3.1.2",
+ "content-type": "~1.0.5",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "on-finished": "2.4.1",
+ "qs": "6.13.0",
+ "raw-body": "2.5.2",
+ "type-is": "~1.6.18",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/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/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/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==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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/cacheable-lookup": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz",
+ "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.6.0"
+ }
+ },
+ "node_modules/cacheable-request": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz",
+ "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==",
+ "license": "MIT",
+ "dependencies": {
+ "clone-response": "^1.0.2",
+ "get-stream": "^5.1.0",
+ "http-cache-semantics": "^4.0.0",
+ "keyv": "^4.0.0",
+ "lowercase-keys": "^2.0.0",
+ "normalize-url": "^6.0.1",
+ "responselike": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=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/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/clean-stack": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/clone": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
+ "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/clone-response": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz",
+ "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==",
+ "license": "MIT",
+ "dependencies": {
+ "mimic-response": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "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/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/content-disposition": {
+ "version": "0.5.4",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
+ "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "5.2.1"
+ },
+ "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/cookie": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
+ "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "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/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==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/data-view-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
+ "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/data-view-byte-length": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz",
+ "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/inspect-js"
+ }
+ },
+ "node_modules/data-view-byte-offset": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz",
+ "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/decompress-response": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
+ "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
+ "license": "MIT",
+ "dependencies": {
+ "mimic-response": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/decompress-response/node_modules/mimic-response": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
+ "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/defer-to-connect": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz",
+ "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "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/define-properties": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
+ "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.0.1",
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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/destroy": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
+ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/diff": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+ "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
+ "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/dynamic-dedupe": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz",
+ "integrity": "sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "xtend": "^4.0.0"
+ }
+ },
+ "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/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/end-of-stream": {
+ "version": "1.4.5",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
+ "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
+ "license": "MIT",
+ "dependencies": {
+ "once": "^1.4.0"
+ }
+ },
+ "node_modules/es-abstract": {
+ "version": "1.24.1",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.1.tgz",
+ "integrity": "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==",
+ "license": "MIT",
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.2",
+ "arraybuffer.prototype.slice": "^1.0.4",
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "data-view-buffer": "^1.0.2",
+ "data-view-byte-length": "^1.0.2",
+ "data-view-byte-offset": "^1.0.1",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "es-set-tostringtag": "^2.1.0",
+ "es-to-primitive": "^1.3.0",
+ "function.prototype.name": "^1.1.8",
+ "get-intrinsic": "^1.3.0",
+ "get-proto": "^1.0.1",
+ "get-symbol-description": "^1.1.0",
+ "globalthis": "^1.0.4",
+ "gopd": "^1.2.0",
+ "has-property-descriptors": "^1.0.2",
+ "has-proto": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "internal-slot": "^1.1.0",
+ "is-array-buffer": "^3.0.5",
+ "is-callable": "^1.2.7",
+ "is-data-view": "^1.0.2",
+ "is-negative-zero": "^2.0.3",
+ "is-regex": "^1.2.1",
+ "is-set": "^2.0.3",
+ "is-shared-array-buffer": "^1.0.4",
+ "is-string": "^1.1.1",
+ "is-typed-array": "^1.1.15",
+ "is-weakref": "^1.1.1",
+ "math-intrinsics": "^1.1.0",
+ "object-inspect": "^1.13.4",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.7",
+ "own-keys": "^1.0.1",
+ "regexp.prototype.flags": "^1.5.4",
+ "safe-array-concat": "^1.1.3",
+ "safe-push-apply": "^1.0.0",
+ "safe-regex-test": "^1.1.0",
+ "set-proto": "^1.0.0",
+ "stop-iteration-iterator": "^1.1.0",
+ "string.prototype.trim": "^1.2.10",
+ "string.prototype.trimend": "^1.0.9",
+ "string.prototype.trimstart": "^1.0.8",
+ "typed-array-buffer": "^1.0.3",
+ "typed-array-byte-length": "^1.0.3",
+ "typed-array-byte-offset": "^1.0.4",
+ "typed-array-length": "^1.0.7",
+ "unbox-primitive": "^1.1.0",
+ "which-typed-array": "^1.1.19"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/es-array-method-boxes-properly": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz",
+ "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==",
+ "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==",
+ "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/es-to-primitive": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz",
+ "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==",
+ "license": "MIT",
+ "dependencies": {
+ "is-callable": "^1.2.7",
+ "is-date-object": "^1.0.5",
+ "is-symbol": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.25.8",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.8.tgz",
+ "integrity": "sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.25.8",
+ "@esbuild/android-arm": "0.25.8",
+ "@esbuild/android-arm64": "0.25.8",
+ "@esbuild/android-x64": "0.25.8",
+ "@esbuild/darwin-arm64": "0.25.8",
+ "@esbuild/darwin-x64": "0.25.8",
+ "@esbuild/freebsd-arm64": "0.25.8",
+ "@esbuild/freebsd-x64": "0.25.8",
+ "@esbuild/linux-arm": "0.25.8",
+ "@esbuild/linux-arm64": "0.25.8",
+ "@esbuild/linux-ia32": "0.25.8",
+ "@esbuild/linux-loong64": "0.25.8",
+ "@esbuild/linux-mips64el": "0.25.8",
+ "@esbuild/linux-ppc64": "0.25.8",
+ "@esbuild/linux-riscv64": "0.25.8",
+ "@esbuild/linux-s390x": "0.25.8",
+ "@esbuild/linux-x64": "0.25.8",
+ "@esbuild/netbsd-arm64": "0.25.8",
+ "@esbuild/netbsd-x64": "0.25.8",
+ "@esbuild/openbsd-arm64": "0.25.8",
+ "@esbuild/openbsd-x64": "0.25.8",
+ "@esbuild/openharmony-arm64": "0.25.8",
+ "@esbuild/sunos-x64": "0.25.8",
+ "@esbuild/win32-arm64": "0.25.8",
+ "@esbuild/win32-ia32": "0.25.8",
+ "@esbuild/win32-x64": "0.25.8"
+ }
+ },
+ "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/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/express": {
+ "version": "4.21.2",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
+ "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "accepts": "~1.3.8",
+ "array-flatten": "1.1.1",
+ "body-parser": "1.20.3",
+ "content-disposition": "0.5.4",
+ "content-type": "~1.0.4",
+ "cookie": "0.7.1",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "1.3.1",
+ "fresh": "0.5.2",
+ "http-errors": "2.0.0",
+ "merge-descriptors": "1.0.3",
+ "methods": "~1.1.2",
+ "on-finished": "2.4.1",
+ "parseurl": "~1.3.3",
+ "path-to-regexp": "0.1.12",
+ "proxy-addr": "~2.0.7",
+ "qs": "6.13.0",
+ "range-parser": "~1.2.1",
+ "safe-buffer": "5.2.1",
+ "send": "0.19.0",
+ "serve-static": "1.16.2",
+ "setprototypeof": "1.2.0",
+ "statuses": "2.0.1",
+ "type-is": "~1.6.18",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.10.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/express-jwt": {
+ "version": "8.5.1",
+ "resolved": "https://registry.npmjs.org/express-jwt/-/express-jwt-8.5.1.tgz",
+ "integrity": "sha512-Dv6QjDLpR2jmdb8M6XQXiCcpEom7mK8TOqnr0/TngDKsG2DHVkO8+XnVxkJVN7BuS1I3OrGw6N8j5DaaGgkDRQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/jsonwebtoken": "^9",
+ "express-unless": "^2.1.3",
+ "jsonwebtoken": "^9.0.0"
+ },
+ "engines": {
+ "node": ">= 8.0.0"
+ }
+ },
+ "node_modules/express-openid-connect": {
+ "version": "2.19.4",
+ "resolved": "https://registry.npmjs.org/express-openid-connect/-/express-openid-connect-2.19.4.tgz",
+ "integrity": "sha512-3YFPZ4MgUPhwfHbCaJKEij7uTc0vF4KpGKsuc3D1IhNMooiP6w8p1HBaaDQOE2KaAas22UghxVECxPpcC/gfOA==",
+ "license": "MIT",
+ "dependencies": {
+ "base64url": "^3.0.1",
+ "clone": "^2.1.2",
+ "cookie": "^0.7.2",
+ "debug": "^4.4.1",
+ "futoin-hkdf": "^1.5.3",
+ "http-errors": "^1.8.1",
+ "joi": "^17.13.3",
+ "jose": "^2.0.7",
+ "on-headers": "^1.1.0",
+ "openid-client": "^4.9.1",
+ "url-join": "^4.0.1",
+ "util-promisify": "3.0.0"
+ },
+ "engines": {
+ "node": "^10.19.0 || >=12.0.0 < 13 || >=13.7.0 < 14 || >= 14.2.0"
+ },
+ "peerDependencies": {
+ "express": ">= 4.17.0"
+ }
+ },
+ "node_modules/express-openid-connect/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/express-openid-connect/node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/express-openid-connect/node_modules/depd": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+ "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/express-openid-connect/node_modules/http-errors": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
+ "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
+ "license": "MIT",
+ "dependencies": {
+ "depd": "~1.1.2",
+ "inherits": "2.0.4",
+ "setprototypeof": "1.2.0",
+ "statuses": ">= 1.5.0 < 2",
+ "toidentifier": "1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/express-openid-connect/node_modules/jose": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/jose/-/jose-2.0.7.tgz",
+ "integrity": "sha512-5hFWIigKqC+e/lRyQhfnirrAqUdIPMB7SJRqflJaO29dW7q5DFvH1XCSTmv6PQ6pb++0k6MJlLRoS0Wv4s38Wg==",
+ "license": "MIT",
+ "dependencies": {
+ "@panva/asn1.js": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=10.13.0 < 13 || >=13.7.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/panva"
+ }
+ },
+ "node_modules/express-openid-connect/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/express-openid-connect/node_modules/statuses": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+ "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/express-unless": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/express-unless/-/express-unless-2.1.3.tgz",
+ "integrity": "sha512-wj4tLMyCVYuIIKHGt0FhCtIViBcwzWejX0EjNxveAa6dG+0XBCQhMbx+PnkLkFCxLC69qoFrxds4pIyL88inaQ==",
+ "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/finalhandler": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz",
+ "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "2.6.9",
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "on-finished": "2.4.1",
+ "parseurl": "~1.3.3",
+ "statuses": "2.0.1",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/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/forwarded": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true,
+ "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/function.prototype.name": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz",
+ "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "functions-have-names": "^1.2.3",
+ "hasown": "^2.0.2",
+ "is-callable": "^1.2.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/futoin-hkdf": {
+ "version": "1.5.3",
+ "resolved": "https://registry.npmjs.org/futoin-hkdf/-/futoin-hkdf-1.5.3.tgz",
+ "integrity": "sha512-SewY5KdMpaoCeh7jachEWFsh1nNlaDjNHZXWqL5IGwtpEYHTgkr2+AMCgNwKWkcc0wpSYrZfR7he4WdmHFtDxQ==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/generator-function": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz",
+ "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/generic-pool": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz",
+ "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/get-stream": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
+ "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
+ "license": "MIT",
+ "dependencies": {
+ "pump": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/get-symbol-description": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz",
+ "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-tsconfig": {
+ "version": "4.10.1",
+ "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz",
+ "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "resolve-pkg-maps": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
+ }
+ },
+ "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/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/globalthis": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
+ "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==",
+ "license": "MIT",
+ "dependencies": {
+ "define-properties": "^1.2.1",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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/got": {
+ "version": "11.8.6",
+ "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz",
+ "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==",
+ "license": "MIT",
+ "dependencies": {
+ "@sindresorhus/is": "^4.0.0",
+ "@szmarczak/http-timer": "^4.0.5",
+ "@types/cacheable-request": "^6.0.1",
+ "@types/responselike": "^1.0.0",
+ "cacheable-lookup": "^5.0.3",
+ "cacheable-request": "^7.0.2",
+ "decompress-response": "^6.0.0",
+ "http2-wrapper": "^1.0.0-beta.5.2",
+ "lowercase-keys": "^2.0.0",
+ "p-cancelable": "^2.0.0",
+ "responselike": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10.19.0"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/got?sponsor=1"
+ }
+ },
+ "node_modules/has-bigints": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz",
+ "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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-proto": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz",
+ "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==",
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "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/http-cache-semantics": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz",
+ "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==",
+ "license": "BSD-2-Clause"
+ },
+ "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/http2-wrapper": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz",
+ "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==",
+ "license": "MIT",
+ "dependencies": {
+ "quick-lru": "^5.1.1",
+ "resolve-alpn": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=10.19.0"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/indent-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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.",
+ "dev": true,
+ "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/internal-slot": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
+ "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "hasown": "^2.0.2",
+ "side-channel": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "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-array-buffer": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
+ "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "get-intrinsic": "^1.2.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-async-function": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz",
+ "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==",
+ "license": "MIT",
+ "dependencies": {
+ "async-function": "^1.0.0",
+ "call-bound": "^1.0.3",
+ "get-proto": "^1.0.1",
+ "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-bigint": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz",
+ "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==",
+ "license": "MIT",
+ "dependencies": {
+ "has-bigints": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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-boolean-object": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz",
+ "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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-core-module": {
+ "version": "2.16.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
+ "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-data-view": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz",
+ "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "get-intrinsic": "^1.2.6",
+ "is-typed-array": "^1.1.13"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-date-object": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz",
+ "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==",
+ "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-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-finalizationregistry": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz",
+ "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-generator-function": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz",
+ "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.4",
+ "generator-function": "^2.0.0",
+ "get-proto": "^1.0.1",
+ "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-map": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
+ "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-negative-zero": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz",
+ "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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-number-object": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz",
+ "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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-set": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz",
+ "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-shared-array-buffer": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz",
+ "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-string": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz",
+ "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-symbol": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz",
+ "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "has-symbols": "^1.1.0",
+ "safe-regex-test": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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/is-weakmap": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
+ "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakref": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz",
+ "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakset": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz",
+ "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "get-intrinsic": "^1.2.6"
+ },
+ "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/joi": {
+ "version": "17.13.3",
+ "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz",
+ "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@hapi/hoek": "^9.3.0",
+ "@hapi/topo": "^5.1.0",
+ "@sideway/address": "^4.1.5",
+ "@sideway/formula": "^3.0.1",
+ "@sideway/pinpoint": "^2.0.0"
+ }
+ },
+ "node_modules/jose": {
+ "version": "4.15.9",
+ "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.9.tgz",
+ "integrity": "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/panva"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "license": "MIT"
+ },
+ "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/jsonwebtoken/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/jwa": {
+ "version": "1.4.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/jwks-rsa": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-3.2.2.tgz",
+ "integrity": "sha512-BqTyEDV+lS8F2trk3A+qJnxV5Q9EqKCBJOPti3W97r7qTympCZjb7h2X6f2kc+0K3rsSTY1/6YG2eaXKoj497w==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/jsonwebtoken": "^9.0.4",
+ "debug": "^4.3.4",
+ "jose": "^4.15.4",
+ "limiter": "^1.1.5",
+ "lru-memoizer": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/jwks-rsa/node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jwks-rsa/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/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/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "license": "MIT",
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/limiter": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz",
+ "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA=="
+ },
+ "node_modules/lodash.clonedeep": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
+ "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.includes": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
+ "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.isboolean": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
+ "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.isinteger": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
+ "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.isnumber": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
+ "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.isplainobject": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
+ "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.isstring": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
+ "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.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/lowercase-keys": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
+ "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/lru-memoizer": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-2.3.0.tgz",
+ "integrity": "sha512-GXn7gyHAMhO13WSKrIiNfztwxodVsP8IoZ3XfrJV4yH2x0/OeTO/FIaAHTY5YekdGgW94njfuKmyyt1E0mR6Ug==",
+ "license": "MIT",
+ "dependencies": {
+ "lodash.clonedeep": "^4.5.0",
+ "lru-cache": "6.0.0"
+ }
+ },
+ "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==",
+ "license": "ISC"
+ },
+ "node_modules/math-intrinsics": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/merge-descriptors": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
+ "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "license": "MIT",
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mimic-response": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
+ "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "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/minimist": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT"
+ },
+ "node_modules/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/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/normalize-url": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz",
+ "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "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-hash": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz",
+ "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "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/object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.assign": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz",
+ "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0",
+ "has-symbols": "^1.1.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.getownpropertydescriptors": {
+ "version": "2.1.9",
+ "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.9.tgz",
+ "integrity": "sha512-mt8YM6XwsTTovI+kdZdHSxoyF2DI59up034orlC9NfweclcWOt7CVascNNLp6U+bjFVCVCIh9PwS76tDM/rH8g==",
+ "license": "MIT",
+ "dependencies": {
+ "array.prototype.reduce": "^1.0.8",
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.24.0",
+ "es-object-atoms": "^1.1.1",
+ "gopd": "^1.2.0",
+ "safe-array-concat": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/oidc-token-hash": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.2.0.tgz",
+ "integrity": "sha512-6gj2m8cJZ+iSW8bm0FXdGF0YhIQbKrfP4yWTNzxc31U6MOjfEmB1rHvlYvxI1B7t7BCi1F2vYTT6YhtQRG4hxw==",
+ "license": "MIT",
+ "engines": {
+ "node": "^10.13.0 || >=12.0.0"
+ }
+ },
+ "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/on-headers": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz",
+ "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==",
+ "license": "MIT",
+ "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/openid-client": {
+ "version": "4.9.1",
+ "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-4.9.1.tgz",
+ "integrity": "sha512-DYUF07AHjI3QDKqKbn2F7RqozT4hyi4JvmpodLrq0HHoNP7t/AjeG/uqiBK1/N2PZSAQEThVjDLHSmJN4iqu/w==",
+ "license": "MIT",
+ "dependencies": {
+ "aggregate-error": "^3.1.0",
+ "got": "^11.8.0",
+ "jose": "^2.0.5",
+ "lru-cache": "^6.0.0",
+ "make-error": "^1.3.6",
+ "object-hash": "^2.0.1",
+ "oidc-token-hash": "^5.0.1"
+ },
+ "engines": {
+ "node": "^10.19.0 || >=12.0.0 < 13 || >=13.7.0 < 14 || >= 14.2.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/panva"
+ }
+ },
+ "node_modules/openid-client/node_modules/jose": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/jose/-/jose-2.0.7.tgz",
+ "integrity": "sha512-5hFWIigKqC+e/lRyQhfnirrAqUdIPMB7SJRqflJaO29dW7q5DFvH1XCSTmv6PQ6pb++0k6MJlLRoS0Wv4s38Wg==",
+ "license": "MIT",
+ "dependencies": {
+ "@panva/asn1.js": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=10.13.0 < 13 || >=13.7.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/panva"
+ }
+ },
+ "node_modules/own-keys": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz",
+ "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==",
+ "license": "MIT",
+ "dependencies": {
+ "get-intrinsic": "^1.2.6",
+ "object-keys": "^1.1.1",
+ "safe-push-apply": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/p-cancelable": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz",
+ "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/path-to-regexp": {
+ "version": "0.1.12",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
+ "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==",
+ "license": "MIT"
+ },
+ "node_modules/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",
+ "peer": true,
+ "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/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/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/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/pump": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz",
+ "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==",
+ "license": "MIT",
+ "dependencies": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "node_modules/qs": {
+ "version": "6.13.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
+ "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "side-channel": "^1.0.6"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/quick-lru": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
+ "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "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": "2.5.2",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
+ "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "3.1.2",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/redis": {
+ "version": "4.7.1",
+ "resolved": "https://registry.npmjs.org/redis/-/redis-4.7.1.tgz",
+ "integrity": "sha512-S1bJDnqLftzHXHP8JsT5II/CtHWQrASX5K96REjWjlmWKrviSOLWmM7QnRLstAWsu1VBBV1ffV6DzCvxNP0UJQ==",
+ "license": "MIT",
+ "workspaces": [
+ "./packages/*"
+ ],
+ "dependencies": {
+ "@redis/bloom": "1.2.0",
+ "@redis/client": "1.6.1",
+ "@redis/graph": "1.1.1",
+ "@redis/json": "1.0.7",
+ "@redis/search": "1.2.0",
+ "@redis/time-series": "1.1.0"
+ }
+ },
+ "node_modules/reflect.getprototypeof": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
+ "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.9",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.7",
+ "get-proto": "^1.0.1",
+ "which-builtin-type": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/regexp.prototype.flags": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
+ "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-errors": "^1.3.0",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "set-function-name": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.22.10",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
+ "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-core-module": "^2.16.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-alpn": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz",
+ "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==",
+ "license": "MIT"
+ },
+ "node_modules/resolve-pkg-maps": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
+ "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
+ }
+ },
+ "node_modules/responselike": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz",
+ "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==",
+ "license": "MIT",
+ "dependencies": {
+ "lowercase-keys": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "deprecated": "Rimraf versions prior to v4 are no longer supported",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ }
+ },
+ "node_modules/safe-array-concat": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz",
+ "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.2",
+ "get-intrinsic": "^1.2.6",
+ "has-symbols": "^1.1.0",
+ "isarray": "^2.0.5"
+ },
+ "engines": {
+ "node": ">=0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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-push-apply": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz",
+ "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "isarray": "^2.0.5"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "license": "MIT"
+ },
+ "node_modules/semver": {
+ "version": "7.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": "0.19.0",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
+ "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "2.0.0",
+ "mime": "1.6.0",
+ "ms": "2.1.3",
+ "on-finished": "2.4.1",
+ "range-parser": "~1.2.1",
+ "statuses": "2.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/send/node_modules/encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/send/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/serve-static": {
+ "version": "1.16.2",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
+ "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
+ "license": "MIT",
+ "dependencies": {
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.3",
+ "send": "0.19.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "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/set-function-name": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
+ "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
+ "functions-have-names": "^1.2.3",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/set-proto": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz",
+ "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==",
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0"
+ },
+ "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/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/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.21",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/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/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/stop-iteration-iterator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz",
+ "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "internal-slot": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/string.prototype.trim": {
+ "version": "1.2.10",
+ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz",
+ "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.2",
+ "define-data-property": "^1.1.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-object-atoms": "^1.0.0",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimend": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz",
+ "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.2",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimstart": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz",
+ "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+ "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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/tree-kill": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
+ "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "tree-kill": "cli.js"
+ }
+ },
+ "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==",
+ "dev": 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/ts-node-dev": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-2.0.0.tgz",
+ "integrity": "sha512-ywMrhCfH6M75yftYvrvNarLEY+SUXtUvU8/0Z6llrHQVBx12GiFk5sStF8UdfE/yfzk9IAq7O5EEbTQsxlBI8w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chokidar": "^3.5.1",
+ "dynamic-dedupe": "^0.3.0",
+ "minimist": "^1.2.6",
+ "mkdirp": "^1.0.4",
+ "resolve": "^1.0.0",
+ "rimraf": "^2.6.1",
+ "source-map-support": "^0.5.12",
+ "tree-kill": "^1.2.2",
+ "ts-node": "^10.4.0",
+ "tsconfig": "^7.0.0"
+ },
+ "bin": {
+ "ts-node-dev": "lib/bin.js",
+ "tsnd": "lib/bin.js"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "*",
+ "typescript": "*"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/tsconfig": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz",
+ "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/strip-bom": "^3.0.0",
+ "@types/strip-json-comments": "0.0.30",
+ "strip-bom": "^3.0.0",
+ "strip-json-comments": "^2.0.0"
+ }
+ },
+ "node_modules/tsx": {
+ "version": "4.20.3",
+ "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.3.tgz",
+ "integrity": "sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "esbuild": "~0.25.0",
+ "get-tsconfig": "^4.7.5"
+ },
+ "bin": {
+ "tsx": "dist/cli.mjs"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ }
+ },
+ "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/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/typed-array-byte-length": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz",
+ "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "for-each": "^0.3.3",
+ "gopd": "^1.2.0",
+ "has-proto": "^1.2.0",
+ "is-typed-array": "^1.1.14"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-byte-offset": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz",
+ "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==",
+ "license": "MIT",
+ "dependencies": {
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.8",
+ "for-each": "^0.3.3",
+ "gopd": "^1.2.0",
+ "has-proto": "^1.2.0",
+ "is-typed-array": "^1.1.15",
+ "reflect.getprototypeof": "^1.0.9"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-length": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz",
+ "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "is-typed-array": "^1.1.13",
+ "possible-typed-array-names": "^1.0.0",
+ "reflect.getprototypeof": "^1.0.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.8.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
+ "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "peer": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/unbox-primitive": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
+ "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.1.0",
+ "which-boxed-primitive": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
+ "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
+ "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/url-join": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz",
+ "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==",
+ "license": "MIT"
+ },
+ "node_modules/util-promisify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/util-promisify/-/util-promisify-3.0.0.tgz",
+ "integrity": "sha512-uWRZJMjSWt/A1J1exfqz7xiKx2kVpAHR5qIDr6WwwBMQHDoKbo2I1kQN62iA2uXHxOSVpZRDvbm8do+4ijfkNA==",
+ "license": "MIT",
+ "dependencies": {
+ "object.getownpropertydescriptors": "^2.0.3"
+ }
+ },
+ "node_modules/utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/uuid": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
+ "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
+ "funding": [
+ "https://github.com/sponsors/broofa",
+ "https://github.com/sponsors/ctavan"
+ ],
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/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==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/which-boxed-primitive": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz",
+ "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==",
+ "license": "MIT",
+ "dependencies": {
+ "is-bigint": "^1.1.0",
+ "is-boolean-object": "^1.2.1",
+ "is-number-object": "^1.1.1",
+ "is-string": "^1.1.1",
+ "is-symbol": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-builtin-type": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz",
+ "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "function.prototype.name": "^1.1.6",
+ "has-tostringtag": "^1.0.2",
+ "is-async-function": "^2.0.0",
+ "is-date-object": "^1.1.0",
+ "is-finalizationregistry": "^1.1.0",
+ "is-generator-function": "^1.0.10",
+ "is-regex": "^1.2.1",
+ "is-weakref": "^1.0.2",
+ "isarray": "^2.0.5",
+ "which-boxed-primitive": "^1.1.0",
+ "which-collection": "^1.0.2",
+ "which-typed-array": "^1.1.16"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-collection": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz",
+ "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==",
+ "license": "MIT",
+ "dependencies": {
+ "is-map": "^2.0.3",
+ "is-set": "^2.0.3",
+ "is-weakmap": "^2.0.2",
+ "is-weakset": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-typed-array": {
+ "version": "1.1.20",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz",
+ "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==",
+ "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/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "license": "ISC"
+ },
+ "node_modules/xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "license": "ISC"
+ },
+ "node_modules/yn": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
+ "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ }
+ }
+}
diff --git a/backend-old-20260125/package.json b/backend-old-20260125/package.json
new file mode 100644
index 0000000..d84d69c
--- /dev/null
+++ b/backend-old-20260125/package.json
@@ -0,0 +1,45 @@
+{
+ "name": "vip-coordinator-backend",
+ "version": "1.0.0",
+ "description": "Backend API for VIP Coordinator Dashboard",
+ "main": "dist/index.js",
+ "scripts": {
+ "start": "node dist/index.js",
+ "dev": "npx tsx src/index.ts",
+ "build": "tsc",
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "keywords": [
+ "vip",
+ "coordinator",
+ "dashboard",
+ "api"
+ ],
+ "author": "",
+ "license": "ISC",
+ "dependencies": {
+ "auth0": "^5.2.0",
+ "cors": "^2.8.5",
+ "dotenv": "^16.3.1",
+ "express": "^4.18.2",
+ "express-jwt": "^8.5.1",
+ "express-openid-connect": "^2.19.4",
+ "jsonwebtoken": "^9.0.2",
+ "jwks-rsa": "^3.2.2",
+ "pg": "^8.11.3",
+ "redis": "^4.6.8",
+ "uuid": "^9.0.0"
+ },
+ "devDependencies": {
+ "@types/cors": "^2.8.13",
+ "@types/express": "^4.17.17",
+ "@types/jsonwebtoken": "^9.0.2",
+ "@types/node": "^20.5.0",
+ "@types/pg": "^8.10.2",
+ "@types/uuid": "^9.0.2",
+ "ts-node": "^10.9.1",
+ "ts-node-dev": "^2.0.0",
+ "tsx": "^4.7.0",
+ "typescript": "^5.6.0"
+ }
+}
diff --git a/backend/public/api-docs.html b/backend-old-20260125/public/api-docs.html
similarity index 100%
rename from backend/public/api-docs.html
rename to backend-old-20260125/public/api-docs.html
diff --git a/backend/public/api-documentation.yaml b/backend-old-20260125/public/api-documentation.yaml
similarity index 100%
rename from backend/public/api-documentation.yaml
rename to backend-old-20260125/public/api-documentation.yaml
diff --git a/backend-old-20260125/src/config/auth0.ts b/backend-old-20260125/src/config/auth0.ts
new file mode 100644
index 0000000..a9cba0a
--- /dev/null
+++ b/backend-old-20260125/src/config/auth0.ts
@@ -0,0 +1,105 @@
+import jwksRsa from 'jwks-rsa';
+import { expressjwt as jwt, GetVerificationKey } from 'express-jwt';
+import { Request, Response, NextFunction } from 'express';
+
+// Environment validation
+const requiredEnvVars = ['AUTH0_DOMAIN', 'AUTH0_AUDIENCE'];
+for (const envVar of requiredEnvVars) {
+ if (!process.env[envVar]) {
+ throw new Error(`Missing required environment variable: ${envVar}`);
+ }
+}
+
+export const auth0Config = {
+ domain: process.env.AUTH0_DOMAIN!,
+ clientId: process.env.AUTH0_CLIENT_ID!,
+ clientSecret: process.env.AUTH0_CLIENT_SECRET!,
+ audience: process.env.AUTH0_AUDIENCE!,
+ apiId: process.env.AUTH0_API_ID!,
+ callbackUrl: process.env.AUTH0_CALLBACK_URL || 'http://localhost:3000/auth/auth0/callback',
+ logoutUrl: process.env.AUTH0_LOGOUT_URL || 'http://localhost:5173/login',
+ frontendUrl: process.env.FRONTEND_URL || 'http://localhost:5173',
+};
+
+// JWKS client for fetching Auth0 public keys
+export const jwksClient = jwksRsa({
+ cache: true,
+ rateLimit: true,
+ jwksRequestsPerMinute: 10,
+ jwksUri: `https://${auth0Config.domain}/.well-known/jwks.json`,
+});
+
+// JWT verification middleware using Auth0's public keys
+export const jwtCheck = jwt({
+ secret: jwksRsa.expressJwtSecret({
+ cache: true,
+ rateLimit: true,
+ jwksRequestsPerMinute: 10,
+ jwksUri: `https://${auth0Config.domain}/.well-known/jwks.json`,
+ }) as GetVerificationKey,
+ audience: auth0Config.audience,
+ issuer: `https://${auth0Config.domain}/`,
+ algorithms: ['RS256'],
+ credentialsRequired: false, // We'll handle this in requireAuth middleware
+});
+
+// Type for decoded JWT payload
+export interface Auth0JwtPayload {
+ iss: string;
+ sub: string;
+ aud: string[];
+ iat: number;
+ exp: number;
+ azp: string;
+ scope?: string;
+ permissions?: string[];
+ // Custom claims
+ 'https://vip-coordinator/role'?: string;
+ 'https://vip-coordinator/approval_status'?: string;
+ 'https://vip-coordinator/email'?: string;
+}
+
+// Extend Express Request to include auth
+declare global {
+ namespace Express {
+ interface Request {
+ auth?: Auth0JwtPayload;
+ }
+ }
+}
+
+// Helper to extract user info from JWT
+export function getUserFromToken(req: Request): {
+ auth0Sub: string;
+ email?: string;
+ role?: string;
+ approvalStatus?: string;
+ permissions?: string[];
+} | null {
+ if (!req.auth) return null;
+
+ return {
+ auth0Sub: req.auth.sub,
+ email: req.auth['https://vip-coordinator/email'],
+ role: req.auth['https://vip-coordinator/role'],
+ approvalStatus: req.auth['https://vip-coordinator/approval_status'],
+ permissions: req.auth.permissions || [],
+ };
+}
+
+// Auth0 Management API configuration
+export function getAuth0ManagementClient() {
+ const { ManagementClient } = require('auth0');
+
+ return new ManagementClient({
+ domain: auth0Config.domain,
+ clientId: auth0Config.clientId,
+ clientSecret: auth0Config.clientSecret,
+ scope: 'read:users update:users read:users_app_metadata update:users_app_metadata',
+ });
+}
+
+console.log('🔐 Auth0 configuration initialized');
+console.log(` Domain: ${auth0Config.domain}`);
+console.log(` Audience: ${auth0Config.audience}`);
+console.log(` JWKS URI: https://${auth0Config.domain}/.well-known/jwks.json`);
diff --git a/backend/src/config/database.ts b/backend-old-20260125/src/config/database.ts
similarity index 100%
rename from backend/src/config/database.ts
rename to backend-old-20260125/src/config/database.ts
diff --git a/backend/src/config/env.ts b/backend-old-20260125/src/config/env.ts
similarity index 100%
rename from backend/src/config/env.ts
rename to backend-old-20260125/src/config/env.ts
diff --git a/backend-old-20260125/src/config/keycloak.ts b/backend-old-20260125/src/config/keycloak.ts
new file mode 100644
index 0000000..b8edee8
--- /dev/null
+++ b/backend-old-20260125/src/config/keycloak.ts
@@ -0,0 +1,102 @@
+import jwksRsa from 'jwks-rsa';
+import { expressjwt as jwt, GetVerificationKey } from 'express-jwt';
+import { Request } from 'express';
+
+// Keycloak configuration
+const keycloakConfig = {
+ realm: process.env.KEYCLOAK_REALM || 'vip-coordinator',
+ serverUrl: process.env.KEYCLOAK_SERVER_URL || 'http://localhost:8080',
+ clientId: process.env.KEYCLOAK_CLIENT_ID || 'vip-coordinator-frontend',
+ frontendUrl: process.env.FRONTEND_URL || 'http://localhost:5173',
+};
+
+// Construct Keycloak URLs
+const realmUrl = `${keycloakConfig.serverUrl}/realms/${keycloakConfig.realm}`;
+const jwksUri = `${realmUrl}/protocol/openid-connect/certs`;
+
+// JWT verification middleware using Keycloak's public keys
+export const jwtCheck = jwt({
+ secret: jwksRsa.expressJwtSecret({
+ cache: true,
+ rateLimit: true,
+ jwksRequestsPerMinute: 10,
+ jwksUri: jwksUri,
+ }) as GetVerificationKey,
+ issuer: realmUrl,
+ algorithms: ['RS256'],
+ credentialsRequired: false, // We'll handle this in requireAuth middleware
+});
+
+// Type for decoded JWT payload (Keycloak format)
+export interface KeycloakJwtPayload {
+ iss: string;
+ sub: string;
+ aud: string | string[];
+ iat: number;
+ exp: number;
+ azp?: string;
+ realm_access?: {
+ roles?: string[];
+ };
+ resource_access?: {
+ [key: string]: {
+ roles?: string[];
+ };
+ };
+ email?: string;
+ email_verified?: boolean;
+ name?: string;
+ preferred_username?: string;
+ given_name?: string;
+ family_name?: string;
+ // Custom claims (if you add them via Keycloak mappers)
+ role?: string;
+ approval_status?: string;
+}
+
+// Extend Express Request to include auth
+declare global {
+ namespace Express {
+ interface Request {
+ auth?: KeycloakJwtPayload;
+ }
+ }
+}
+
+// Helper to extract user info from JWT
+export function getUserFromToken(req: Request): {
+ keycloakSub: string;
+ email?: string;
+ name?: string;
+ role?: string;
+ approvalStatus?: string;
+ roles?: string[];
+} | null {
+ if (!req.auth) return null;
+
+ const roles = req.auth.realm_access?.roles || [];
+
+ return {
+ keycloakSub: req.auth.sub,
+ email: req.auth.email,
+ name: req.auth.name || req.auth.preferred_username,
+ role: req.auth.role, // Custom claim if you add it
+ approvalStatus: req.auth.approval_status, // Custom claim if you add it
+ roles: roles,
+ };
+}
+
+export const keycloakUrls = {
+ realmUrl,
+ jwksUri,
+ authorizationUrl: `${realmUrl}/protocol/openid-connect/auth`,
+ tokenUrl: `${realmUrl}/protocol/openid-connect/token`,
+ logoutUrl: `${realmUrl}/protocol/openid-connect/logout`,
+ userInfoUrl: `${realmUrl}/protocol/openid-connect/userinfo`,
+};
+
+console.log('🔐 Keycloak configuration initialized');
+console.log(` Realm: ${keycloakConfig.realm}`);
+console.log(` Server URL: ${keycloakConfig.serverUrl}`);
+console.log(` Client ID: ${keycloakConfig.clientId}`);
+console.log(` JWKS URI: ${jwksUri}`);
diff --git a/backend/src/config/mockDatabase.ts b/backend-old-20260125/src/config/mockDatabase.ts
similarity index 100%
rename from backend/src/config/mockDatabase.ts
rename to backend-old-20260125/src/config/mockDatabase.ts
diff --git a/backend/src/config/redis.ts b/backend-old-20260125/src/config/redis.ts
similarity index 100%
rename from backend/src/config/redis.ts
rename to backend-old-20260125/src/config/redis.ts
diff --git a/backend/src/config/schema.sql b/backend-old-20260125/src/config/schema.sql
similarity index 94%
rename from backend/src/config/schema.sql
rename to backend-old-20260125/src/config/schema.sql
index 20b72fe..c3f70f7 100644
--- a/backend/src/config/schema.sql
+++ b/backend-old-20260125/src/config/schema.sql
@@ -63,7 +63,7 @@ CREATE TABLE IF NOT EXISTS schedule_events (
-- Create users table for authentication
CREATE TABLE IF NOT EXISTS users (
id VARCHAR(255) PRIMARY KEY,
- google_id VARCHAR(255) UNIQUE NOT NULL,
+ auth0_sub VARCHAR(255) UNIQUE NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
name VARCHAR(255) NOT NULL,
role VARCHAR(50) NOT NULL CHECK (role IN ('driver', 'coordinator', 'administrator')),
@@ -71,7 +71,9 @@ CREATE TABLE IF NOT EXISTS users (
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_login TIMESTAMP,
is_active BOOLEAN DEFAULT true,
- updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ approval_status VARCHAR(20) DEFAULT 'pending' CHECK (approval_status IN ('pending', 'approved', 'denied')),
+ identity_provider VARCHAR(50) DEFAULT 'auth0'
);
-- Create system_setup table for tracking initial setup
@@ -100,7 +102,7 @@ CREATE INDEX IF NOT EXISTS idx_schedule_events_vip_id ON schedule_events(vip_id)
CREATE INDEX IF NOT EXISTS idx_schedule_events_driver_id ON schedule_events(assigned_driver_id);
CREATE INDEX IF NOT EXISTS idx_schedule_events_start_time ON schedule_events(start_time);
CREATE INDEX IF NOT EXISTS idx_schedule_events_status ON schedule_events(status);
-CREATE INDEX IF NOT EXISTS idx_users_google_id ON users(google_id);
+CREATE INDEX IF NOT EXISTS idx_users_auth0_sub ON users(auth0_sub);
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
CREATE INDEX IF NOT EXISTS idx_users_role ON users(role);
CREATE INDEX IF NOT EXISTS idx_drivers_user_id ON drivers(user_id);
diff --git a/backend/src/index.original.ts b/backend-old-20260125/src/index.original.ts
similarity index 100%
rename from backend/src/index.original.ts
rename to backend-old-20260125/src/index.original.ts
diff --git a/backend/src/index.ts b/backend-old-20260125/src/index.ts
similarity index 96%
rename from backend/src/index.ts
rename to backend-old-20260125/src/index.ts
index ccad26f..16f7990 100644
--- a/backend/src/index.ts
+++ b/backend-old-20260125/src/index.ts
@@ -1,14 +1,15 @@
import express, { Express, Request, Response } from 'express';
import dotenv from 'dotenv';
import cors from 'cors';
-import authRoutes, { requireAuth, requireRole } from './routes/simpleAuth';
+import authRoutes from './routes/auth'; // Keycloak routes
+import { jwtCheck } from './config/keycloak'; // Keycloak JWT middleware
+import { requireAuth, requireRole } from './middleware/auth'; // Auth middleware
import flightService from './services/flightService';
import driverConflictService from './services/driverConflictService';
import scheduleValidationService from './services/scheduleValidationService';
import FlightTrackingScheduler from './services/flightTrackingScheduler';
import enhancedDataService from './services/enhancedDataService';
import databaseService from './services/databaseService';
-import jwtKeyManager from './services/jwtKeyManager'; // Initialize JWT Key Manager
dotenv.config();
@@ -29,10 +30,13 @@ app.use(cors({
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
-// Simple JWT-based authentication - no passport needed
+// Authentication routes (under /api prefix to match frontend)
+// Must be BEFORE jwtCheck middleware so public routes work
+app.use('/api/auth', authRoutes);
-// Authentication routes
-app.use('/auth', authRoutes);
+// Keycloak JWT validation middleware (applied globally to all other routes)
+// Routes defined above this are NOT protected by JWT
+app.use(jwtCheck);
// Temporary admin bypass route (remove after setup)
app.get('/admin-bypass', (req: Request, res: Response) => {
@@ -47,17 +51,13 @@ app.get('/api/health', async (req: Request, res: Response) => {
try {
const timestamp = new Date().toISOString();
- // Check JWT Key Manager status
- const jwtStatus = jwtKeyManager.getStatus();
-
- // Check environment variables
- const envCheck = {
- google_client_id: !!process.env.GOOGLE_CLIENT_ID,
- google_client_secret: !!process.env.GOOGLE_CLIENT_SECRET,
- google_redirect_uri: !!process.env.GOOGLE_REDIRECT_URI,
+ // Check Auth0 configuration
+ const authConfig = {
+ auth0_domain: !!process.env.AUTH0_DOMAIN,
+ auth0_client_id: !!process.env.AUTH0_CLIENT_ID,
+ auth0_audience: !!process.env.AUTH0_AUDIENCE,
frontend_url: !!process.env.FRONTEND_URL,
- database_url: !!process.env.DATABASE_URL,
- admin_password: !!process.env.ADMIN_PASSWORD
+ database_url: !!process.env.DATABASE_URL
};
// Check database connectivity
@@ -73,9 +73,8 @@ app.get('/api/health', async (req: Request, res: Response) => {
// Overall system health
const isHealthy = databaseStatus === 'connected' &&
- jwtStatus.hasCurrentKey &&
- envCheck.google_client_id &&
- envCheck.google_client_secret;
+ authConfig.auth0_domain &&
+ authConfig.auth0_client_id;
const healthData = {
status: isHealthy ? 'OK' : 'DEGRADED',
@@ -88,9 +87,9 @@ app.get('/api/health', async (req: Request, res: Response) => {
user_count: databaseStatus === 'connected' ? userCount : null
},
authentication: {
- jwt_key_manager: jwtStatus,
- oauth_configured: envCheck.google_client_id && envCheck.google_client_secret,
- environment_variables: envCheck
+ provider: 'auth0',
+ auth0_configured: authConfig.auth0_domain && authConfig.auth0_client_id,
+ environment_variables: authConfig
}
},
uptime: process.uptime(),
@@ -101,8 +100,7 @@ app.get('/api/health', async (req: Request, res: Response) => {
console.log(`🏥 Health Check [${timestamp}]:`, {
status: healthData.status,
database: databaseStatus,
- jwt_keys: jwtStatus.hasCurrentKey,
- oauth: envCheck.google_client_id && envCheck.google_client_secret
+ auth0: authConfig.auth0_domain && authConfig.auth0_client_id
});
res.status(isHealthy ? 200 : 503).json(healthData);
diff --git a/backend/src/indexSimplified.ts b/backend-old-20260125/src/indexSimplified.ts
similarity index 100%
rename from backend/src/indexSimplified.ts
rename to backend-old-20260125/src/indexSimplified.ts
diff --git a/backend-old-20260125/src/middleware/auth.ts b/backend-old-20260125/src/middleware/auth.ts
new file mode 100644
index 0000000..b93cfd4
--- /dev/null
+++ b/backend-old-20260125/src/middleware/auth.ts
@@ -0,0 +1,133 @@
+import { Request, Response, NextFunction } from 'express';
+import { getUserFromToken } from '../config/keycloak';
+
+/**
+ * Middleware to require authentication
+ * Checks if JWT is present and valid
+ */
+export function requireAuth(req: Request, res: Response, next: NextFunction) {
+ if (!req.auth) {
+ return res.status(401).json({
+ error: 'unauthorized',
+ message: 'Authentication required. Please log in.',
+ });
+ }
+
+ next();
+}
+
+/**
+ * Middleware to require specific role
+ * @param allowedRoles - Array of allowed roles or single role
+ */
+export function requireRole(...allowedRoles: string[]) {
+ return (req: Request, res: Response, next: NextFunction) => {
+ const user = getUserFromToken(req);
+
+ if (!user) {
+ return res.status(401).json({
+ error: 'unauthorized',
+ message: 'Authentication required.',
+ });
+ }
+
+ if (!user.role || !allowedRoles.includes(user.role)) {
+ return res.status(403).json({
+ error: 'forbidden',
+ message: `Access denied. Required role: ${allowedRoles.join(' or ')}`,
+ userRole: user.role,
+ });
+ }
+
+ next();
+ };
+}
+
+/**
+ * Middleware to require specific permission
+ * @param requiredPermissions - Array of required permissions
+ */
+export function requirePermission(...requiredPermissions: string[]) {
+ return (req: Request, res: Response, next: NextFunction) => {
+ const user = getUserFromToken(req);
+
+ if (!user) {
+ return res.status(401).json({
+ error: 'unauthorized',
+ message: 'Authentication required.',
+ });
+ }
+
+ const userPermissions = user.permissions || [];
+ const hasPermission = requiredPermissions.some(permission =>
+ userPermissions.includes(permission)
+ );
+
+ if (!hasPermission) {
+ return res.status(403).json({
+ error: 'forbidden',
+ message: `Access denied. Required permission: ${requiredPermissions.join(' or ')}`,
+ userPermissions,
+ });
+ }
+
+ next();
+ };
+}
+
+/**
+ * Middleware to check if user has been approved
+ * Redirects pending users to pending approval page
+ */
+export function checkApprovalStatus(req: Request, res: Response, next: NextFunction) {
+ const user = getUserFromToken(req);
+
+ if (!user) {
+ return res.status(401).json({
+ error: 'unauthorized',
+ message: 'Authentication required.',
+ });
+ }
+
+ const approvalStatus = user.approvalStatus;
+
+ if (approvalStatus === 'denied') {
+ return res.status(403).json({
+ error: 'access_denied',
+ message: 'Your access has been denied by an administrator.',
+ });
+ }
+
+ if (approvalStatus === 'pending') {
+ return res.status(403).json({
+ error: 'approval_pending',
+ message: 'Your account is pending approval from an administrator.',
+ redirectTo: '/pending-approval',
+ });
+ }
+
+ // If approved or no status (first user/admin), continue
+ next();
+}
+
+/**
+ * Middleware to require administrator role
+ */
+export const requireAdmin = requireRole('administrator');
+
+/**
+ * Middleware to require coordinator or administrator role
+ */
+export const requireCoordinatorOrAdmin = requireRole('coordinator', 'administrator');
+
+/**
+ * Optional auth middleware - doesn't fail if no auth present
+ * Useful for routes that work with or without authentication
+ */
+export function optionalAuth(req: Request, res: Response, next: NextFunction) {
+ // JWT middleware already ran with credentialsRequired: false
+ // Just continue regardless of auth state
+ next();
+}
+
+console.log('🛡️ Auth middleware initialized');
diff --git a/backend/src/middleware/errorHandler.ts b/backend-old-20260125/src/middleware/errorHandler.ts
similarity index 100%
rename from backend/src/middleware/errorHandler.ts
rename to backend-old-20260125/src/middleware/errorHandler.ts
diff --git a/backend/src/middleware/logger.ts b/backend-old-20260125/src/middleware/logger.ts
similarity index 100%
rename from backend/src/middleware/logger.ts
rename to backend-old-20260125/src/middleware/logger.ts
diff --git a/backend/src/middleware/simpleValidation.ts b/backend-old-20260125/src/middleware/simpleValidation.ts
similarity index 100%
rename from backend/src/middleware/simpleValidation.ts
rename to backend-old-20260125/src/middleware/simpleValidation.ts
diff --git a/backend/src/middleware/validation.ts b/backend-old-20260125/src/middleware/validation.ts
similarity index 100%
rename from backend/src/middleware/validation.ts
rename to backend-old-20260125/src/middleware/validation.ts
diff --git a/backend/src/migrations/add_user_management_fields.sql b/backend-old-20260125/src/migrations/add_user_management_fields.sql
similarity index 100%
rename from backend/src/migrations/add_user_management_fields.sql
rename to backend-old-20260125/src/migrations/add_user_management_fields.sql
diff --git a/backend/src/routes/__tests__/vips.test.ts b/backend-old-20260125/src/routes/__tests__/vips.test.ts
similarity index 100%
rename from backend/src/routes/__tests__/vips.test.ts
rename to backend-old-20260125/src/routes/__tests__/vips.test.ts
diff --git a/backend-old-20260125/src/routes/auth.ts b/backend-old-20260125/src/routes/auth.ts
new file mode 100644
index 0000000..27df226
--- /dev/null
+++ b/backend-old-20260125/src/routes/auth.ts
@@ -0,0 +1,239 @@
+import express, { Request, Response, Router } from 'express';
+import { keycloakUrls, getUserFromToken } from '../config/keycloak';
+import { syncUserFromKeycloak, getAllUsers, getPendingUsers, approveUser, denyUser, assignRole } from '../services/userService';
+import { requireAuth, requireAdmin, checkApprovalStatus } from '../middleware/auth';
+import databaseService from '../services/databaseService';
+
+const router: Router = express.Router();
+
+const frontendUrl = process.env.FRONTEND_URL || 'http://localhost:5173';
+const keycloakClientId = process.env.KEYCLOAK_CLIENT_ID || 'vip-coordinator-frontend';
+
+/**
+ * GET /auth/login
+ * Redirects to Keycloak login
+ */
+router.get('/login', (req: Request, res: Response) => {
+ const returnTo = req.query.returnTo as string || '/';
+
+ const authUrl = `${keycloakUrls.authorizationUrl}?` +
+ `client_id=${keycloakClientId}&` +
+ `redirect_uri=${encodeURIComponent(`${frontendUrl}/auth/callback`)}&` +
+ `response_type=code&` +
+ `scope=openid profile email&` +
+ `state=${encodeURIComponent(returnTo)}`;
+
+ res.redirect(authUrl);
+});
+
+/**
+ * GET /auth/logout
+ * Logs out user from Keycloak and app
+ */
+router.get('/logout', (req: Request, res: Response) => {
+ const logoutUrl = `${keycloakUrls.logoutUrl}?` +
+ `client_id=${keycloakClientId}&` +
+ `post_logout_redirect_uri=${encodeURIComponent(`${frontendUrl}/login`)}`;
+
+ res.redirect(logoutUrl);
+});
+
+/**
+ * GET /auth/me
+ * Returns current user information
+ * Protected route - requires authentication
+ */
+router.get('/me', requireAuth, async (req: Request, res: Response) => {
+ try {
+ const user = getUserFromToken(req);
+
+ if (!user) {
+ return res.status(401).json({ error: 'Not authenticated' });
+ }
+
+ // Get access token from Authorization header
+ const authHeader = req.headers.authorization;
+ const token = authHeader?.replace('Bearer ', '');
+
+ if (!token) {
+ return res.status(401).json({ error: 'No token provided' });
+ }
+
+ // Sync user to local database (creates if doesn't exist, updates if exists)
+ await syncUserFromKeycloak(user.keycloakSub, token);
+
+ // Fetch full user details from database
+ const dbUser = await databaseService.getUserByAuth0Sub(user.keycloakSub);
+
+ if (!dbUser) {
+ return res.status(404).json({ error: 'User not found in database' });
+ }
+
+ res.json({
+ user: dbUser,
+ keycloak: {
+ sub: user.keycloakSub,
+ roles: user.roles,
+ },
+ });
+ } catch (error) {
+ console.error('❌ Error fetching user:', error);
+ res.status(500).json({ error: 'Failed to fetch user information' });
+ }
+});
+
+/**
+ * GET /auth/status
+ * Returns authentication status
+ */
+router.get('/status', requireAuth, (req: Request, res: Response) => {
+ const user = getUserFromToken(req);
+
+ res.json({
+ authenticated: true,
+ user: {
+ keycloakSub: user?.keycloakSub,
+ email: user?.email,
+ role: user?.role,
+ approvalStatus: user?.approvalStatus,
+ },
+ });
+});
+
+/**
+ * GET /auth/setup
+ * Check if system setup is complete (first user created)
+ */
+router.get('/setup', async (req: Request, res: Response) => {
+ try {
+ const userCount = await databaseService.getUserCount();
+ const hasUsers = userCount > 0;
+
+ res.json({
+ setupComplete: hasUsers,
+ needsFirstUser: !hasUsers,
+ });
+ } catch (error) {
+ console.error('❌ Error checking setup status:', error);
+ res.status(500).json({ error: 'Failed to check setup status' });
+ }
+});
+
+// ============================================
+// User Management Routes (Admin Only)
+// ============================================
+
+/**
+ * GET /auth/users
+ * Get all users
+ * Admin only
+ */
+router.get('/users', requireAuth, requireAdmin, async (req: Request, res: Response) => {
+ try {
+ const users = await getAllUsers();
+ res.json({ users });
+ } catch (error) {
+ console.error('❌ Error fetching users:', error);
+ res.status(500).json({ error: 'Failed to fetch users' });
+ }
+});
+
+/**
+ * GET /auth/users/pending/list
+ * Get pending users
+ * Admin only
+ */
+router.get('/users/pending/list', requireAuth, requireAdmin, async (req: Request, res: Response) => {
+ try {
+ const users = await getPendingUsers();
+ res.json({ users });
+ } catch (error) {
+ console.error('❌ Error fetching pending users:', error);
+ res.status(500).json({ error: 'Failed to fetch pending users' });
+ }
+});
+
+/**
+ * PATCH /auth/users/:email/approval
+ * Approve or deny a user
+ * Admin only
+ */
+router.patch('/users/:email/approval', requireAuth, requireAdmin, async (req: Request, res: Response) => {
+ const { email } = req.params;
+ const { status } = req.body; // 'approved' or 'denied'
+
+ if (!status || !['approved', 'denied'].includes(status)) {
+ return res.status(400).json({ error: 'Invalid status. Must be "approved" or "denied"' });
+ }
+
+ try {
+ if (status === 'approved') {
+ await approveUser(email);
+ } else {
+ await denyUser(email);
+ }
+
+ res.json({
+ success: true,
+ message: `User ${email} has been ${status}`,
+ });
+ } catch (error) {
+ console.error(`❌ Error updating approval status for ${email}:`, error);
+ res.status(500).json({ error: 'Failed to update user approval status' });
+ }
+});
+
+/**
+ * PATCH /auth/users/:email/role
+ * Change user role
+ * Admin only
+ */
+router.patch('/users/:email/role', requireAuth, requireAdmin, async (req: Request, res: Response) => {
+ const { email } = req.params;
+ const { role } = req.body;
+
+ if (!role || !['driver', 'coordinator', 'administrator'].includes(role)) {
+ return res.status(400).json({ error: 'Invalid role. Must be "driver", "coordinator", or "administrator"' });
+ }
+
+ try {
+ await assignRole(email, role);
+
+ res.json({
+ success: true,
+ message: `User ${email} role updated to ${role}`,
+ });
+ } catch (error) {
+ console.error(`❌ Error updating role for ${email}:`, error);
+ res.status(500).json({ error: 'Failed to update user role' });
+ }
+});
+
+/**
+ * DELETE /auth/users/:email
+ * Delete a user
+ * Admin only
+ */
+router.delete('/users/:email', requireAuth, requireAdmin, async (req: Request, res: Response) => {
+ const { email } = req.params;
+
+ try {
+ const result = await databaseService.query('DELETE FROM users WHERE email = $1 RETURNING *', [email]);
+
+ if (result.rows.length === 0) {
+ return res.status(404).json({ error: 'User not found' });
+ }
+
+ res.json({
+ success: true,
+ message: `User ${email} has been deleted`,
+ });
+ } catch (error) {
+ console.error(`❌ Error deleting user ${email}:`, error);
+ res.status(500).json({ error: 'Failed to delete user' });
+ }
+});
+
+console.log('🔐 Auth routes initialized (Keycloak)');
+
+export default router;
diff --git a/backend/src/scripts/check-and-fix-users.sql b/backend-old-20260125/src/scripts/check-and-fix-users.sql
similarity index 100%
rename from backend/src/scripts/check-and-fix-users.sql
rename to backend-old-20260125/src/scripts/check-and-fix-users.sql
diff --git a/backend/src/scripts/db-cli.ts b/backend-old-20260125/src/scripts/db-cli.ts
similarity index 100%
rename from backend/src/scripts/db-cli.ts
rename to backend-old-20260125/src/scripts/db-cli.ts
diff --git a/backend/src/scripts/fix-existing-user-admin.js b/backend-old-20260125/src/scripts/fix-existing-user-admin.js
similarity index 100%
rename from backend/src/scripts/fix-existing-user-admin.js
rename to backend-old-20260125/src/scripts/fix-existing-user-admin.js
diff --git a/backend/src/scripts/fix-first-admin-docker.js b/backend-old-20260125/src/scripts/fix-first-admin-docker.js
similarity index 100%
rename from backend/src/scripts/fix-first-admin-docker.js
rename to backend-old-20260125/src/scripts/fix-first-admin-docker.js
diff --git a/backend/src/scripts/fix-first-admin.js b/backend-old-20260125/src/scripts/fix-first-admin.js
similarity index 100%
rename from backend/src/scripts/fix-first-admin.js
rename to backend-old-20260125/src/scripts/fix-first-admin.js
diff --git a/backend/src/scripts/fix-specific-user-admin.js b/backend-old-20260125/src/scripts/fix-specific-user-admin.js
similarity index 100%
rename from backend/src/scripts/fix-specific-user-admin.js
rename to backend-old-20260125/src/scripts/fix-specific-user-admin.js
diff --git a/backend/src/services/__tests__/authService.test.ts b/backend-old-20260125/src/services/__tests__/authService.test.ts
similarity index 100%
rename from backend/src/services/__tests__/authService.test.ts
rename to backend-old-20260125/src/services/__tests__/authService.test.ts
diff --git a/backend/src/services/dataService.ts b/backend-old-20260125/src/services/dataService.ts
similarity index 100%
rename from backend/src/services/dataService.ts
rename to backend-old-20260125/src/services/dataService.ts
diff --git a/backend/src/services/databaseService.ts b/backend-old-20260125/src/services/databaseService.ts
similarity index 95%
rename from backend/src/services/databaseService.ts
rename to backend-old-20260125/src/services/databaseService.ts
index ddb5434..f4bdbb6 100644
--- a/backend/src/services/databaseService.ts
+++ b/backend-old-20260125/src/services/databaseService.ts
@@ -74,11 +74,11 @@ class DatabaseService {
// Initialize database tables
async initializeTables(): Promise {
try {
- // Create users table (matching the actual schema)
+ // Create users table (matching the actual schema with auth0_sub)
await this.query(`
CREATE TABLE IF NOT EXISTS users (
id VARCHAR(255) PRIMARY KEY,
- google_id VARCHAR(255) UNIQUE NOT NULL,
+ auth0_sub VARCHAR(255) UNIQUE NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
name VARCHAR(255) NOT NULL,
role VARCHAR(50) NOT NULL CHECK (role IN ('driver', 'coordinator', 'administrator')),
@@ -87,7 +87,8 @@ class DatabaseService {
last_login TIMESTAMP,
is_active BOOLEAN DEFAULT true,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
- approval_status VARCHAR(20) DEFAULT 'pending' CHECK (approval_status IN ('pending', 'approved', 'denied'))
+ approval_status VARCHAR(20) DEFAULT 'pending' CHECK (approval_status IN ('pending', 'approved', 'denied')),
+ identity_provider VARCHAR(50) DEFAULT 'auth0'
)
`);
@@ -97,9 +98,15 @@ class DatabaseService {
ADD COLUMN IF NOT EXISTS approval_status VARCHAR(20) DEFAULT 'pending' CHECK (approval_status IN ('pending', 'approved', 'denied'))
`);
+ // Add identity_provider column if it doesn't exist
+ await this.query(`
+ ALTER TABLE users
+ ADD COLUMN IF NOT EXISTS identity_provider VARCHAR(50) DEFAULT 'auth0'
+ `);
+
// Create indexes
await this.query(`
- CREATE INDEX IF NOT EXISTS idx_users_google_id ON users(google_id)
+ CREATE INDEX IF NOT EXISTS idx_users_auth0_sub ON users(auth0_sub)
`);
await this.query(`
@@ -120,21 +127,21 @@ class DatabaseService {
// User management methods
async createUser(user: {
id: string;
- google_id: string;
+ auth0_sub: string;
email: string;
name: string;
profile_picture_url?: string;
role: string;
}): Promise {
const query = `
- INSERT INTO users (id, google_id, email, name, profile_picture_url, role, last_login)
- VALUES ($1, $2, $3, $4, $5, $6, CURRENT_TIMESTAMP)
+ INSERT INTO users (id, auth0_sub, email, name, profile_picture_url, role, last_login, identity_provider)
+ VALUES ($1, $2, $3, $4, $5, $6, CURRENT_TIMESTAMP, 'auth0')
RETURNING *
`;
const values = [
user.id,
- user.google_id,
+ user.auth0_sub,
user.email,
user.name,
user.profile_picture_url || null,
@@ -158,6 +165,12 @@ class DatabaseService {
return result.rows[0] || null;
}
+ async getUserByAuth0Sub(auth0Sub: string): Promise {
+ const query = 'SELECT * FROM users WHERE auth0_sub = $1';
+ const result = await this.query(query, [auth0Sub]);
+ return result.rows[0] || null;
+ }
+
async getAllUsers(): Promise {
const query = 'SELECT * FROM users ORDER BY created_at ASC';
const result = await this.query(query);
diff --git a/backend/src/services/driverConflictService.ts b/backend-old-20260125/src/services/driverConflictService.ts
similarity index 100%
rename from backend/src/services/driverConflictService.ts
rename to backend-old-20260125/src/services/driverConflictService.ts
diff --git a/backend/src/services/enhancedDataService.ts b/backend-old-20260125/src/services/enhancedDataService.ts
similarity index 100%
rename from backend/src/services/enhancedDataService.ts
rename to backend-old-20260125/src/services/enhancedDataService.ts
diff --git a/backend/src/services/flightService.ts b/backend-old-20260125/src/services/flightService.ts
similarity index 100%
rename from backend/src/services/flightService.ts
rename to backend-old-20260125/src/services/flightService.ts
diff --git a/backend/src/services/flightTrackingScheduler.ts b/backend-old-20260125/src/services/flightTrackingScheduler.ts
similarity index 100%
rename from backend/src/services/flightTrackingScheduler.ts
rename to backend-old-20260125/src/services/flightTrackingScheduler.ts
diff --git a/backend/src/services/migrationService.ts b/backend-old-20260125/src/services/migrationService.ts
similarity index 100%
rename from backend/src/services/migrationService.ts
rename to backend-old-20260125/src/services/migrationService.ts
diff --git a/backend/src/services/scheduleValidationService.ts b/backend-old-20260125/src/services/scheduleValidationService.ts
similarity index 100%
rename from backend/src/services/scheduleValidationService.ts
rename to backend-old-20260125/src/services/scheduleValidationService.ts
diff --git a/backend/src/services/seedService.ts b/backend-old-20260125/src/services/seedService.ts
similarity index 100%
rename from backend/src/services/seedService.ts
rename to backend-old-20260125/src/services/seedService.ts
diff --git a/backend/src/services/unifiedDataService.ts b/backend-old-20260125/src/services/unifiedDataService.ts
similarity index 100%
rename from backend/src/services/unifiedDataService.ts
rename to backend-old-20260125/src/services/unifiedDataService.ts
diff --git a/backend-old-20260125/src/services/userService.ts b/backend-old-20260125/src/services/userService.ts
new file mode 100644
index 0000000..7e7125a
--- /dev/null
+++ b/backend-old-20260125/src/services/userService.ts
@@ -0,0 +1,199 @@
+import { pool } from './databaseService';
+import { keycloakUrls } from '../config/keycloak';
+
+export interface UserMetadata {
+ approval_status: 'pending' | 'approved' | 'denied';
+ role: 'driver' | 'coordinator' | 'administrator';
+}
+
+/**
+ * Sync user from Keycloak to local database
+ * Creates or updates user record based on JWT token
+ */
+export async function syncUserFromKeycloak(keycloakSub: string, token: string): Promise {
+ try {
+ // Fetch user info from Keycloak
+ const userInfoResponse = await fetch(keycloakUrls.userInfoUrl, {
+ headers: {
+ 'Authorization': `Bearer ${token}`,
+ },
+ });
+
+ if (!userInfoResponse.ok) {
+ throw new Error('Failed to fetch user info from Keycloak');
+ }
+
+ const userInfo = await userInfoResponse.json();
+
+ // Extract user details
+ const email = userInfo.email;
+ const name = userInfo.name || userInfo.preferred_username || email;
+ const picture = userInfo.picture;
+
+ // Check if this is the first user (should be administrator)
+ const userCountResult = await pool.query('SELECT COUNT(*) as count FROM users');
+ const isFirstUser = parseInt(userCountResult.rows[0].count) === 0;
+
+ const finalRole = isFirstUser ? 'administrator' : 'driver';
+ const finalApprovalStatus = isFirstUser ? 'approved' : 'pending';
+
+ // Upsert user in local database
+ // Note: Keeping auth0_sub column name for now (it's just a name, stores Keycloak sub)
+ const query = `
+ INSERT INTO users (id, auth0_sub, email, name, role, profile_picture_url, approval_status, last_login, identity_provider)
+ VALUES ($1, $2, $3, $4, $5, $6, $7, NOW(), 'keycloak')
+ ON CONFLICT (auth0_sub)
+ DO UPDATE SET
+ email = EXCLUDED.email,
+ name = EXCLUDED.name,
+ role = EXCLUDED.role,
+ profile_picture_url = EXCLUDED.profile_picture_url,
+ approval_status = EXCLUDED.approval_status,
+ last_login = NOW(),
+ updated_at = NOW()
+ RETURNING *
+ `;
+
+ const userId = keycloakSub.replace(/:/g, '_'); // Convert keycloak UUID to safe ID
+ const values = [userId, keycloakSub, email, name, finalRole, picture, finalApprovalStatus];
+ const result = await pool.query(query, values);
+
+ console.log(`✅ Synced user from Keycloak: ${email} (${finalRole}, ${finalApprovalStatus})`);
+ return result.rows[0];
+ } catch (error) {
+ console.error('❌ Error syncing user from Keycloak:', error);
+ throw error;
+ }
+}
+
+/**
+ * Update user metadata in local database
+ * Note: Keycloak doesn't have app_metadata like Auth0, so we store everything in local DB
+ */
+export async function updateUserMetadata(
+ keycloakSub: string,
+ metadata: Partial
+): Promise {
+ try {
+ const updates: string[] = [];
+ const values: any[] = [];
+ let paramCount = 1;
+
+ if (metadata.role) {
+ updates.push(`role = $${paramCount++}`);
+ values.push(metadata.role);
+ }
+
+ if (metadata.approval_status) {
+ updates.push(`approval_status = $${paramCount++}`);
+ values.push(metadata.approval_status);
+ }
+
+ if (updates.length === 0) {
+ return;
+ }
+
+ updates.push(`updated_at = NOW()`);
+ values.push(keycloakSub);
+
+ const query = `
+ UPDATE users
+ SET ${updates.join(', ')}
+ WHERE auth0_sub = $${paramCount}
+ `;
+
+ await pool.query(query, values);
+
+ console.log(`✅ Updated user metadata for ${keycloakSub}:`, metadata);
+ } catch (error) {
+ console.error('❌ Error updating user metadata:', error);
+ throw error;
+ }
+}
+
+/**
+ * Approve a user (update local DB)
+ */
+export async function approveUser(email: string): Promise {
+ try {
+ // Update local DB
+ await pool.query(
+ 'UPDATE users SET approval_status = $1, updated_at = NOW() WHERE email = $2',
+ ['approved', email]
+ );
+
+ console.log(`✅ Approved user: ${email}`);
+ } catch (error) {
+ console.error(`❌ Error approving user ${email}:`, error);
+ throw error;
+ }
+}
+
+/**
+ * Deny a user (update local DB)
+ */
+export async function denyUser(email: string): Promise {
+ try {
+ // Update local DB
+ await pool.query(
+ 'UPDATE users SET approval_status = $1, updated_at = NOW() WHERE email = $2',
+ ['denied', email]
+ );
+
+ console.log(`✅ Denied user: ${email}`);
+ } catch (error) {
+ console.error(`❌ Error denying user ${email}:`, error);
+ throw error;
+ }
+}
+
+/**
+ * Assign a role to a user (update local DB)
+ */
+export async function assignRole(
+ email: string,
+ role: 'driver' | 'coordinator' | 'administrator'
+): Promise {
+ try {
+ // Update local DB
+ await pool.query(
+ 'UPDATE users SET role = $1, updated_at = NOW() WHERE email = $2',
+ [role, email]
+ );
+
+ console.log(`✅ Assigned role ${role} to user: ${email}`);
+ } catch (error) {
+ console.error(`❌ Error assigning role to user ${email}:`, error);
+ throw error;
+ }
+}
+
+/**
+ * Get all users from local DB
+ */
+export async function getAllUsers(): Promise {
+ const result = await pool.query(`
+ SELECT id, auth0_sub, email, name, role, profile_picture_url,
+ approval_status, created_at, last_login, is_active
+ FROM users
+ ORDER BY created_at DESC
+ `);
+
+ return result.rows;
+}
+
+/**
+ * Get pending users
+ */
+export async function getPendingUsers(): Promise {
+ const result = await pool.query(`
+ SELECT id, auth0_sub, email, name, role, profile_picture_url, created_at
+ FROM users
+ WHERE approval_status = 'pending'
+ ORDER BY created_at DESC
+ `);
+
+ return result.rows;
+}
+
+console.log('👥 User service initialized (Keycloak)');
diff --git a/backend/src/tests/fixtures.ts b/backend-old-20260125/src/tests/fixtures.ts
similarity index 100%
rename from backend/src/tests/fixtures.ts
rename to backend-old-20260125/src/tests/fixtures.ts
diff --git a/backend/src/tests/setup.ts b/backend-old-20260125/src/tests/setup.ts
similarity index 100%
rename from backend/src/tests/setup.ts
rename to backend-old-20260125/src/tests/setup.ts
diff --git a/backend/src/types/api.ts b/backend-old-20260125/src/types/api.ts
similarity index 100%
rename from backend/src/types/api.ts
rename to backend-old-20260125/src/types/api.ts
diff --git a/backend/src/types/errors.ts b/backend-old-20260125/src/types/errors.ts
similarity index 100%
rename from backend/src/types/errors.ts
rename to backend-old-20260125/src/types/errors.ts
diff --git a/backend/src/types/schemas.ts b/backend-old-20260125/src/types/schemas.ts
similarity index 100%
rename from backend/src/types/schemas.ts
rename to backend-old-20260125/src/types/schemas.ts
diff --git a/backend-old-20260125/tsconfig.json b/backend-old-20260125/tsconfig.json
new file mode 100644
index 0000000..05f269c
--- /dev/null
+++ b/backend-old-20260125/tsconfig.json
@@ -0,0 +1,21 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "module": "commonjs",
+ "lib": ["ES2020", "DOM"],
+ "outDir": "./dist",
+ "rootDir": "./src",
+ "strict": true,
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "forceConsistentCasingInFileNames": true,
+ "resolveJsonModule": true,
+ "declaration": true,
+ "declarationMap": true,
+ "sourceMap": true,
+ "types": ["node"],
+ "moduleResolution": "node"
+ },
+ "include": ["src/**/*"],
+ "exclude": ["node_modules", "dist"]
+}
diff --git a/backend/.env b/backend/.env
index cca41a3..490e182 100644
--- a/backend/.env
+++ b/backend/.env
@@ -1,26 +1,33 @@
-# Database Configuration
-DATABASE_URL=postgresql://postgres:changeme@db:5432/vip_coordinator
-
-# Redis Configuration
-REDIS_URL=redis://redis:6379
-
-# Authentication Configuration
-JWT_SECRET=your-super-secure-jwt-secret-key-change-in-production-12345
-SESSION_SECRET=your-super-secure-session-secret-change-in-production-67890
-
-# Google OAuth Configuration (optional for local development)
-GOOGLE_CLIENT_ID=308004695553-6k34bbq22frc4e76kejnkgq8mncepbbg.apps.googleusercontent.com
-GOOGLE_CLIENT_SECRET=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
-GOOGLE_REDIRECT_URI=https://api.bsa.madeamess.online/auth/google/callback
-
-# Frontend URL
-FRONTEND_URL=https://bsa.madeamess.online
-
-# Flight API Configuration
-AVIATIONSTACK_API_KEY=your-aviationstack-api-key
-
-# Admin Configuration
-ADMIN_PASSWORD=admin123
-
-# Port Configuration
+# ============================================
+# Application Configuration
+# ============================================
PORT=3000
+NODE_ENV=development
+FRONTEND_URL=http://localhost:5173
+
+# ============================================
+# Database Configuration
+# ============================================
+DATABASE_URL="postgresql://postgres:changeme@localhost:5433/vip_coordinator"
+
+# ============================================
+# Redis Configuration (Optional)
+# ============================================
+REDIS_URL="redis://localhost:6379"
+
+# ============================================
+# Auth0 Configuration
+# ============================================
+# Get these from your Auth0 dashboard:
+# 1. Create Application (Single Page Application)
+# 2. Create API
+# 3. Configure callback URLs: http://localhost:5173/callback
+AUTH0_DOMAIN="dev-s855cy3bvjjbkljt.us.auth0.com"
+AUTH0_AUDIENCE="https://vip-coordinator-api"
+AUTH0_ISSUER="https://dev-s855cy3bvjjbkljt.us.auth0.com/"
+
+# ============================================
+# Flight Tracking API (Optional)
+# ============================================
+# Get API key from: https://aviationstack.com/
+AVIATIONSTACK_API_KEY="your-aviationstack-api-key"
diff --git a/backend/.env.example b/backend/.env.example
index 3bfe644..5342e42 100644
--- a/backend/.env.example
+++ b/backend/.env.example
@@ -1,22 +1,28 @@
-# Database Configuration
-DATABASE_URL=postgresql://postgres:password@db:5432/vip_coordinator
-
-# Redis Configuration
-REDIS_URL=redis://redis:6379
-
-# Authentication Configuration
-JWT_SECRET=your-super-secure-jwt-secret-key-change-in-production
-SESSION_SECRET=your-super-secure-session-secret-change-in-production
-
-# Google OAuth Configuration
-GOOGLE_CLIENT_ID=your-google-client-id-from-console
-GOOGLE_CLIENT_SECRET=your-google-client-secret-from-console
-
-# Frontend URL
+# ============================================
+# Application Configuration
+# ============================================
+PORT=3000
+NODE_ENV=development
FRONTEND_URL=http://localhost:5173
-# Flight API Configuration
-AVIATIONSTACK_API_KEY=your-aviationstack-api-key
+# ============================================
+# Database Configuration
+# ============================================
+DATABASE_URL="postgresql://postgres:changeme@localhost:5432/vip_coordinator"
-# Admin Configuration
-ADMIN_PASSWORD=admin123
+# ============================================
+# Redis Configuration (Optional)
+# ============================================
+REDIS_URL="redis://localhost:6379"
+
+# ============================================
+# Auth0 Configuration
+# ============================================
+AUTH0_DOMAIN="your-tenant.us.auth0.com"
+AUTH0_AUDIENCE="https://your-api-identifier"
+AUTH0_ISSUER="https://your-tenant.us.auth0.com/"
+
+# ============================================
+# Flight Tracking API (Optional)
+# ============================================
+AVIATIONSTACK_API_KEY="your-aviationstack-api-key"
diff --git a/backend/.gitignore b/backend/.gitignore
new file mode 100644
index 0000000..9099a4a
--- /dev/null
+++ b/backend/.gitignore
@@ -0,0 +1,43 @@
+# compiled output
+/dist
+/node_modules
+
+# Logs
+logs
+*.log
+npm-debug.log*
+pnpm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+lerna-debug.log*
+
+# OS
+.DS_Store
+
+# Tests
+/coverage
+/.nyc_output
+
+# IDEs and editors
+/.idea
+.project
+.classpath
+.c9/
+*.launch
+.settings/
+*.sublime-workspace
+
+# IDE - VSCode
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+
+# Environment
+.env
+.env.local
+.env.production
+
+# Prisma
+prisma/migrations/.migrate_lock
diff --git a/backend/README.md b/backend/README.md
new file mode 100644
index 0000000..710a185
--- /dev/null
+++ b/backend/README.md
@@ -0,0 +1,134 @@
+# VIP Coordinator Backend
+
+NestJS 10.x backend with Prisma ORM, Auth0 authentication, and PostgreSQL.
+
+## Quick Start
+
+```bash
+# Install dependencies
+npm install
+
+# Set up environment variables
+cp .env.example .env
+# Edit .env with your Auth0 credentials
+
+# Start PostgreSQL (via Docker)
+cd ..
+docker-compose up -d postgres
+
+# Generate Prisma Client
+npx prisma generate
+
+# Run database migrations
+npx prisma migrate dev
+
+# Seed sample data (optional)
+npm run prisma:seed
+
+# Start development server
+npm run start:dev
+```
+
+## API Endpoints
+
+All endpoints are prefixed with `/api/v1`
+
+### Public Endpoints
+- `GET /health` - Health check
+
+### Authentication
+- `GET /auth/profile` - Get current user profile
+
+### Users (Admin only)
+- `GET /users` - List all users
+- `GET /users/pending` - List pending approval users
+- `GET /users/:id` - Get user by ID
+- `PATCH /users/:id` - Update user
+- `PATCH /users/:id/approve` - Approve/deny user
+- `DELETE /users/:id` - Delete user (soft)
+
+### VIPs (Admin, Coordinator)
+- `GET /vips` - List all VIPs
+- `POST /vips` - Create VIP
+- `GET /vips/:id` - Get VIP by ID
+- `PATCH /vips/:id` - Update VIP
+- `DELETE /vips/:id` - Delete VIP (soft)
+
+### Drivers (Admin, Coordinator)
+- `GET /drivers` - List all drivers
+- `POST /drivers` - Create driver
+- `GET /drivers/:id` - Get driver by ID
+- `GET /drivers/:id/schedule` - Get driver schedule
+- `PATCH /drivers/:id` - Update driver
+- `DELETE /drivers/:id` - Delete driver (soft)
+
+### Events (Admin, Coordinator; Drivers can view and update status)
+- `GET /events` - List all events
+- `POST /events` - Create event (with conflict detection)
+- `GET /events/:id` - Get event by ID
+- `PATCH /events/:id` - Update event
+- `PATCH /events/:id/status` - Update event status
+- `DELETE /events/:id` - Delete event (soft)
+
+### Flights (Admin, Coordinator)
+- `GET /flights` - List all flights
+- `POST /flights` - Create flight
+- `GET /flights/status/:flightNumber` - Get real-time flight status
+- `GET /flights/vip/:vipId` - Get flights for VIP
+- `GET /flights/:id` - Get flight by ID
+- `PATCH /flights/:id` - Update flight
+- `DELETE /flights/:id` - Delete flight
+
+## Development Commands
+
+```bash
+npm run start:dev # Start dev server with hot reload
+npm run build # Build for production
+npm run start:prod # Start production server
+npm run lint # Run ESLint
+npm run test # Run tests
+npm run test:watch # Run tests in watch mode
+npm run test:cov # Run tests with coverage
+```
+
+## Database Commands
+
+```bash
+npx prisma studio # Open Prisma Studio (database GUI)
+npx prisma migrate dev # Create and apply migration
+npx prisma migrate deploy # Apply migrations (production)
+npx prisma migrate reset # Reset database (DEV ONLY)
+npx prisma generate # Regenerate Prisma Client
+npm run prisma:seed # Seed database with sample data
+```
+
+## Environment Variables
+
+See `.env.example` for all required variables:
+
+- `DATABASE_URL` - PostgreSQL connection string
+- `AUTH0_DOMAIN` - Your Auth0 tenant domain
+- `AUTH0_AUDIENCE` - Your Auth0 API identifier
+- `AUTH0_ISSUER` - Your Auth0 issuer URL
+- `AVIATIONSTACK_API_KEY` - Flight tracking API key (optional)
+
+## Features
+
+- ✅ Auth0 JWT authentication
+- ✅ Role-based access control (Administrator, Coordinator, Driver)
+- ✅ User approval workflow
+- ✅ VIP management
+- ✅ Driver management
+- ✅ Event scheduling with conflict detection
+- ✅ Flight tracking integration
+- ✅ Soft deletes for all entities
+- ✅ Comprehensive validation
+- ✅ Type-safe database queries with Prisma
+
+## Tech Stack
+
+- **Framework:** NestJS 10.x
+- **Database:** PostgreSQL 15+ with Prisma 5.x ORM
+- **Authentication:** Auth0 + Passport JWT
+- **Validation:** class-validator + class-transformer
+- **HTTP Client:** @nestjs/axios (for flight tracking)
diff --git a/backend/nest-cli.json b/backend/nest-cli.json
new file mode 100644
index 0000000..f9aa683
--- /dev/null
+++ b/backend/nest-cli.json
@@ -0,0 +1,8 @@
+{
+ "$schema": "https://json.schemastore.org/nest-cli",
+ "collection": "@nestjs/schematics",
+ "sourceRoot": "src",
+ "compilerOptions": {
+ "deleteOutDir": true
+ }
+}
diff --git a/backend/package-lock.json b/backend/package-lock.json
index 4c3617b..dd8bc14 100644
--- a/backend/package-lock.json
+++ b/backend/package-lock.json
@@ -7,29 +7,778 @@
"": {
"name": "vip-coordinator-backend",
"version": "1.0.0",
- "license": "ISC",
+ "license": "MIT",
"dependencies": {
- "cors": "^2.8.5",
- "dotenv": "^16.3.1",
- "express": "^4.18.2",
- "google-auth-library": "^10.1.0",
- "jsonwebtoken": "^9.0.2",
- "pg": "^8.11.3",
- "redis": "^4.6.8",
- "uuid": "^9.0.0",
- "zod": "^3.22.4"
+ "@casl/ability": "^6.8.0",
+ "@casl/prisma": "^1.6.1",
+ "@nestjs/axios": "^4.0.1",
+ "@nestjs/common": "^10.3.0",
+ "@nestjs/config": "^3.1.1",
+ "@nestjs/core": "^10.3.0",
+ "@nestjs/jwt": "^10.2.0",
+ "@nestjs/mapped-types": "^2.1.0",
+ "@nestjs/passport": "^10.0.3",
+ "@nestjs/platform-express": "^10.3.0",
+ "@prisma/client": "^5.8.1",
+ "axios": "^1.6.5",
+ "class-transformer": "^0.5.1",
+ "class-validator": "^0.14.0",
+ "ioredis": "^5.3.2",
+ "jwks-rsa": "^3.1.0",
+ "passport": "^0.7.0",
+ "passport-jwt": "^4.0.1",
+ "reflect-metadata": "^0.1.14",
+ "rxjs": "^7.8.1"
},
"devDependencies": {
- "@types/cors": "^2.8.13",
- "@types/express": "^4.17.17",
- "@types/jsonwebtoken": "^9.0.2",
- "@types/node": "^20.5.0",
- "@types/pg": "^8.10.2",
- "@types/uuid": "^9.0.2",
- "ts-node": "^10.9.1",
- "ts-node-dev": "^2.0.0",
- "tsx": "^4.7.0",
- "typescript": "^5.6.0"
+ "@nestjs/cli": "^10.2.1",
+ "@nestjs/schematics": "^10.0.3",
+ "@nestjs/testing": "^10.3.0",
+ "@types/express": "^4.17.21",
+ "@types/jest": "^29.5.11",
+ "@types/node": "^20.10.6",
+ "@types/passport-jwt": "^4.0.0",
+ "@types/supertest": "^6.0.2",
+ "@typescript-eslint/eslint-plugin": "^6.17.0",
+ "@typescript-eslint/parser": "^6.17.0",
+ "eslint": "^8.56.0",
+ "eslint-config-prettier": "^9.1.0",
+ "eslint-plugin-prettier": "^5.1.2",
+ "jest": "^29.7.0",
+ "prettier": "^3.1.1",
+ "prisma": "^5.8.1",
+ "source-map-support": "^0.5.21",
+ "supertest": "^6.3.3",
+ "ts-jest": "^29.1.1",
+ "ts-loader": "^9.5.1",
+ "ts-node": "^10.9.2",
+ "tsconfig-paths": "^4.2.0",
+ "typescript": "^5.3.3"
+ }
+ },
+ "node_modules/@angular-devkit/core": {
+ "version": "17.3.11",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-17.3.11.tgz",
+ "integrity": "sha512-vTNDYNsLIWpYk2I969LMQFH29GTsLzxNk/0cLw5q56ARF0v5sIWfHYwGTS88jdDqIpuuettcSczbxeA7EuAmqQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "8.12.0",
+ "ajv-formats": "2.1.1",
+ "jsonc-parser": "3.2.1",
+ "picomatch": "4.0.1",
+ "rxjs": "7.8.1",
+ "source-map": "0.7.4"
+ },
+ "engines": {
+ "node": "^18.13.0 || >=20.9.0",
+ "npm": "^6.11.0 || ^7.5.6 || >=8.0.0",
+ "yarn": ">= 1.13.0"
+ },
+ "peerDependencies": {
+ "chokidar": "^3.5.2"
+ },
+ "peerDependenciesMeta": {
+ "chokidar": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@angular-devkit/core/node_modules/rxjs": {
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
+ "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@angular-devkit/schematics": {
+ "version": "17.3.11",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-17.3.11.tgz",
+ "integrity": "sha512-I5wviiIqiFwar9Pdk30Lujk8FczEEc18i22A5c6Z9lbmhPQdTroDnEQdsfXjy404wPe8H62s0I15o4pmMGfTYQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@angular-devkit/core": "17.3.11",
+ "jsonc-parser": "3.2.1",
+ "magic-string": "0.30.8",
+ "ora": "5.4.1",
+ "rxjs": "7.8.1"
+ },
+ "engines": {
+ "node": "^18.13.0 || >=20.9.0",
+ "npm": "^6.11.0 || ^7.5.6 || >=8.0.0",
+ "yarn": ">= 1.13.0"
+ }
+ },
+ "node_modules/@angular-devkit/schematics-cli": {
+ "version": "17.3.11",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/schematics-cli/-/schematics-cli-17.3.11.tgz",
+ "integrity": "sha512-kcOMqp+PHAKkqRad7Zd7PbpqJ0LqLaNZdY1+k66lLWmkEBozgq8v4ASn/puPWf9Bo0HpCiK+EzLf0VHE8Z/y6Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@angular-devkit/core": "17.3.11",
+ "@angular-devkit/schematics": "17.3.11",
+ "ansi-colors": "4.1.3",
+ "inquirer": "9.2.15",
+ "symbol-observable": "4.0.0",
+ "yargs-parser": "21.1.1"
+ },
+ "bin": {
+ "schematics": "bin/schematics.js"
+ },
+ "engines": {
+ "node": "^18.13.0 || >=20.9.0",
+ "npm": "^6.11.0 || ^7.5.6 || >=8.0.0",
+ "yarn": ">= 1.13.0"
+ }
+ },
+ "node_modules/@angular-devkit/schematics-cli/node_modules/chalk": {
+ "version": "5.6.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz",
+ "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.17.0 || ^14.13 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/@angular-devkit/schematics-cli/node_modules/cli-width": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz",
+ "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/@angular-devkit/schematics-cli/node_modules/inquirer": {
+ "version": "9.2.15",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.15.tgz",
+ "integrity": "sha512-vI2w4zl/mDluHt9YEQ/543VTCwPKWiHzKtm9dM2V0NdFcqEexDAjUHzO1oA60HRNaVifGXXM1tRRNluLVHa0Kg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@ljharb/through": "^2.3.12",
+ "ansi-escapes": "^4.3.2",
+ "chalk": "^5.3.0",
+ "cli-cursor": "^3.1.0",
+ "cli-width": "^4.1.0",
+ "external-editor": "^3.1.0",
+ "figures": "^3.2.0",
+ "lodash": "^4.17.21",
+ "mute-stream": "1.0.0",
+ "ora": "^5.4.1",
+ "run-async": "^3.0.0",
+ "rxjs": "^7.8.1",
+ "string-width": "^4.2.3",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^6.2.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@angular-devkit/schematics-cli/node_modules/mute-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz",
+ "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@angular-devkit/schematics-cli/node_modules/run-async": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz",
+ "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/@angular-devkit/schematics/node_modules/rxjs": {
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
+ "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.28.6.tgz",
+ "integrity": "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.28.5",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.6.tgz",
+ "integrity": "sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.6.tgz",
+ "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.28.6",
+ "@babel/generator": "^7.28.6",
+ "@babel/helper-compilation-targets": "^7.28.6",
+ "@babel/helper-module-transforms": "^7.28.6",
+ "@babel/helpers": "^7.28.6",
+ "@babel/parser": "^7.28.6",
+ "@babel/template": "^7.28.6",
+ "@babel/traverse": "^7.28.6",
+ "@babel/types": "^7.28.6",
+ "@jridgewell/remapping": "^2.3.5",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/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.6",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.6.tgz",
+ "integrity": "sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.28.6",
+ "@babel/types": "^7.28.6",
+ "@jridgewell/gen-mapping": "^0.3.12",
+ "@jridgewell/trace-mapping": "^0.3.28",
+ "jsesc": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz",
+ "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/compat-data": "^7.28.6",
+ "@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/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.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz",
+ "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.28.6",
+ "@babel/types": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz",
+ "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.28.6",
+ "@babel/helper-validator-identifier": "^7.28.5",
+ "@babel/traverse": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz",
+ "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==",
+ "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.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
+ "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
+ "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz",
+ "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.28.6",
+ "@babel/types": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.6.tgz",
+ "integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.28.6"
+ },
+ "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.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz",
+ "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.28.6"
+ },
+ "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.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz",
+ "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.28.6"
+ },
+ "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.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz",
+ "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz",
+ "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.28.6",
+ "@babel/parser": "^7.28.6",
+ "@babel/types": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.6.tgz",
+ "integrity": "sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.28.6",
+ "@babel/generator": "^7.28.6",
+ "@babel/helper-globals": "^7.28.0",
+ "@babel/parser": "^7.28.6",
+ "@babel/template": "^7.28.6",
+ "@babel/types": "^7.28.6",
+ "debug": "^4.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.6.tgz",
+ "integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.28.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@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/@borewit/text-codec": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/@borewit/text-codec/-/text-codec-0.2.1.tgz",
+ "integrity": "sha512-k7vvKPbf7J2fZ5klGRD9AeKfUvojuZIQ3BT5u7Jfv+puwXkUBUT5PVyMDfJZpy30CBDXGMgw7fguK/lpOMBvgw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Borewit"
+ }
+ },
+ "node_modules/@casl/ability": {
+ "version": "6.8.0",
+ "resolved": "https://registry.npmjs.org/@casl/ability/-/ability-6.8.0.tgz",
+ "integrity": "sha512-Ipt4mzI4gSgnomFdaPjaLgY2MWuXqAEZLrU6qqWBB7khGiBBuuEp6ytYDnq09bRXqcjaeeHiaCvCGFbBA2SpvA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@ucast/mongo2js": "^1.3.0"
+ },
+ "funding": {
+ "url": "https://github.com/stalniy/casl/blob/master/BACKERS.md"
+ }
+ },
+ "node_modules/@casl/prisma": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/@casl/prisma/-/prisma-1.6.1.tgz",
+ "integrity": "sha512-VSAzfTMOZvP3Atj3F0qwJItOm1ixIiumjbBz21PL/gLUIDwoktyAx2dB7dPwjH9AQvzZPE629ee7fVU5K2hpzg==",
+ "license": "MIT",
+ "dependencies": {
+ "@ucast/core": "^1.10.0",
+ "@ucast/js": "^3.0.1"
+ },
+ "peerDependencies": {
+ "@casl/ability": "^5.3.0 || ^6.0.0",
+ "@prisma/client": "^2.14.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
+ }
+ },
+ "node_modules/@colors/colors": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz",
+ "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=0.1.90"
}
},
"node_modules/@cspotcode/source-map-support": {
@@ -45,446 +794,774 @@
"node": ">=12"
}
},
- "node_modules/@esbuild/aix-ppc64": {
- "version": "0.25.8",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.8.tgz",
- "integrity": "sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA==",
- "cpu": [
- "ppc64"
- ],
+ "node_modules/@cspotcode/source-map-support/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==",
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "aix"
- ],
- "engines": {
- "node": ">=18"
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.0.3",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
}
},
- "node_modules/@esbuild/android-arm": {
- "version": "0.25.8",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.8.tgz",
- "integrity": "sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw==",
- "cpu": [
- "arm"
- ],
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.9.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz",
+ "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==",
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
+ "dependencies": {
+ "eslint-visitor-keys": "^3.4.3"
+ },
"engines": {
- "node": ">=18"
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
}
},
- "node_modules/@esbuild/android-arm64": {
- "version": "0.25.8",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.8.tgz",
- "integrity": "sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w==",
- "cpu": [
- "arm64"
- ],
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.12.2",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
+ "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==",
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
"engines": {
- "node": ">=18"
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
}
},
- "node_modules/@esbuild/android-x64": {
- "version": "0.25.8",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.8.tgz",
- "integrity": "sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA==",
- "cpu": [
- "x64"
- ],
+ "node_modules/@eslint/eslintrc": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
+ "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.6.0",
+ "globals": "^13.19.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
"engines": {
- "node": ">=18"
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
}
},
- "node_modules/@esbuild/darwin-arm64": {
- "version": "0.25.8",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.8.tgz",
- "integrity": "sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw==",
- "cpu": [
- "arm64"
- ],
+ "node_modules/@eslint/eslintrc/node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=18"
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
}
},
- "node_modules/@esbuild/darwin-x64": {
- "version": "0.25.8",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.8.tgz",
- "integrity": "sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg==",
- "cpu": [
- "x64"
- ],
+ "node_modules/@eslint/eslintrc/node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=18"
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
}
},
- "node_modules/@esbuild/freebsd-arm64": {
- "version": "0.25.8",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.8.tgz",
- "integrity": "sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA==",
- "cpu": [
- "arm64"
- ],
+ "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
"dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
+ "license": "MIT"
+ },
+ "node_modules/@eslint/eslintrc/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
"engines": {
- "node": ">=18"
+ "node": "*"
}
},
- "node_modules/@esbuild/freebsd-x64": {
- "version": "0.25.8",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.8.tgz",
- "integrity": "sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw==",
- "cpu": [
- "x64"
- ],
+ "node_modules/@eslint/js": {
+ "version": "8.57.1",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz",
+ "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==",
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
"engines": {
- "node": ">=18"
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
- "node_modules/@esbuild/linux-arm": {
- "version": "0.25.8",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.8.tgz",
- "integrity": "sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg==",
- "cpu": [
- "arm"
- ],
+ "node_modules/@humanwhocodes/config-array": {
+ "version": "0.13.0",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
+ "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==",
+ "deprecated": "Use @eslint/config-array instead",
"dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@humanwhocodes/object-schema": "^2.0.3",
+ "debug": "^4.3.1",
+ "minimatch": "^3.0.5"
+ },
"engines": {
- "node": ">=18"
+ "node": ">=10.10.0"
}
},
- "node_modules/@esbuild/linux-arm64": {
- "version": "0.25.8",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.8.tgz",
- "integrity": "sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w==",
- "cpu": [
- "arm64"
- ],
+ "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
}
},
- "node_modules/@esbuild/linux-ia32": {
- "version": "0.25.8",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.8.tgz",
- "integrity": "sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg==",
- "cpu": [
- "ia32"
- ],
+ "node_modules/@humanwhocodes/config-array/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
"engines": {
- "node": ">=18"
+ "node": "*"
}
},
- "node_modules/@esbuild/linux-loong64": {
- "version": "0.25.8",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.8.tgz",
- "integrity": "sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ==",
- "cpu": [
- "loong64"
- ],
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
"dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
+ "license": "Apache-2.0",
"engines": {
- "node": ">=18"
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
}
},
- "node_modules/@esbuild/linux-mips64el": {
- "version": "0.25.8",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.8.tgz",
- "integrity": "sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw==",
- "cpu": [
- "mips64el"
- ],
+ "node_modules/@humanwhocodes/object-schema": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
+ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
+ "deprecated": "Use @eslint/object-schema instead",
"dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@ioredis/commands": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.5.0.tgz",
+ "integrity": "sha512-eUgLqrMf8nJkZxT24JvVRrQya1vZkQh8BBeYNwGDqa5I0VUi8ACx7uFvAaLxintokpTenkK6DASvo/bvNbBGow==",
+ "license": "MIT"
+ },
+ "node_modules/@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+ },
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
- "node_modules/@esbuild/linux-ppc64": {
- "version": "0.25.8",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.8.tgz",
- "integrity": "sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ==",
- "cpu": [
- "ppc64"
- ],
+ "node_modules/@isaacs/cliui/node_modules/ansi-regex": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
+ "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
"engines": {
- "node": ">=18"
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
- "node_modules/@esbuild/linux-riscv64": {
- "version": "0.25.8",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.8.tgz",
- "integrity": "sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg==",
- "cpu": [
- "riscv64"
- ],
+ "node_modules/@isaacs/cliui/node_modules/ansi-styles": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz",
+ "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==",
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
"engines": {
- "node": ">=18"
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/@esbuild/linux-s390x": {
- "version": "0.25.8",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.8.tgz",
- "integrity": "sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg==",
- "cpu": [
- "s390x"
- ],
+ "node_modules/@isaacs/cliui/node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@isaacs/cliui/node_modules/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
"engines": {
- "node": ">=18"
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/@esbuild/linux-x64": {
- "version": "0.25.8",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.8.tgz",
- "integrity": "sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ==",
- "cpu": [
- "x64"
- ],
+ "node_modules/@isaacs/cliui/node_modules/strip-ansi": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz",
+ "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==",
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
"engines": {
- "node": ">=18"
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
- "node_modules/@esbuild/netbsd-arm64": {
- "version": "0.25.8",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.8.tgz",
- "integrity": "sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw==",
- "cpu": [
- "arm64"
- ],
+ "node_modules/@isaacs/cliui/node_modules/wrap-ansi": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
+ "dependencies": {
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
+ },
"engines": {
- "node": ">=18"
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
- "node_modules/@esbuild/netbsd-x64": {
- "version": "0.25.8",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.8.tgz",
- "integrity": "sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg==",
- "cpu": [
- "x64"
- ],
+ "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": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
+ "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": ">=18"
+ "node": ">=8"
}
},
- "node_modules/@esbuild/openbsd-arm64": {
- "version": "0.25.8",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.8.tgz",
- "integrity": "sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ==",
- "cpu": [
- "arm64"
- ],
+ "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",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=18"
+ "dependencies": {
+ "sprintf-js": "~1.0.2"
}
},
- "node_modules/@esbuild/openbsd-x64": {
- "version": "0.25.8",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.8.tgz",
- "integrity": "sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ==",
- "cpu": [
- "x64"
- ],
+ "node_modules/@istanbuljs/load-nyc-config/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",
- "optional": true,
- "os": [
- "openbsd"
- ],
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
"engines": {
- "node": ">=18"
+ "node": ">=8"
}
},
- "node_modules/@esbuild/openharmony-arm64": {
- "version": "0.25.8",
- "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.8.tgz",
- "integrity": "sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg==",
- "cpu": [
- "arm64"
- ],
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": {
+ "version": "3.14.2",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
+ "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "openharmony"
- ],
- "engines": {
- "node": ">=18"
+ "dependencies": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
}
},
- "node_modules/@esbuild/sunos-x64": {
- "version": "0.25.8",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.8.tgz",
- "integrity": "sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w==",
- "cpu": [
- "x64"
- ],
+ "node_modules/@istanbuljs/load-nyc-config/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",
- "optional": true,
- "os": [
- "sunos"
- ],
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
"engines": {
- "node": ">=18"
+ "node": ">=8"
}
},
- "node_modules/@esbuild/win32-arm64": {
- "version": "0.25.8",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.8.tgz",
- "integrity": "sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ==",
- "cpu": [
- "arm64"
- ],
+ "node_modules/@istanbuljs/load-nyc-config/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",
- "optional": true,
- "os": [
- "win32"
- ],
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
"engines": {
- "node": ">=18"
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/@esbuild/win32-ia32": {
- "version": "0.25.8",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.8.tgz",
- "integrity": "sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg==",
- "cpu": [
- "ia32"
- ],
+ "node_modules/@istanbuljs/load-nyc-config/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",
- "optional": true,
- "os": [
- "win32"
- ],
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
"engines": {
- "node": ">=18"
+ "node": ">=8"
}
},
- "node_modules/@esbuild/win32-x64": {
- "version": "0.25.8",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.8.tgz",
- "integrity": "sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw==",
- "cpu": [
- "x64"
- ],
+ "node_modules/@istanbuljs/load-nyc-config/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",
- "optional": true,
- "os": [
- "win32"
- ],
"engines": {
- "node": ">=18"
+ "node": ">=8"
+ }
+ },
+ "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": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz",
+ "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/core": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz",
+ "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/console": "^29.7.0",
+ "@jest/reporters": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.9",
+ "jest-changed-files": "^29.7.0",
+ "jest-config": "^29.7.0",
+ "jest-haste-map": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-resolve-dependencies": "^29.7.0",
+ "jest-runner": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "jest-watcher": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@jest/environment": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz",
+ "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-mock": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/expect": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz",
+ "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "expect": "^29.7.0",
+ "jest-snapshot": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/expect-utils": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz",
+ "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jest-get-type": "^29.6.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/fake-timers": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz",
+ "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@sinonjs/fake-timers": "^10.0.2",
+ "@types/node": "*",
+ "jest-message-util": "^29.7.0",
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/globals": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz",
+ "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/expect": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "jest-mock": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/reporters": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz",
+ "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@bcoe/v8-coverage": "^0.2.3",
+ "@jest/console": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "collect-v8-coverage": "^1.0.0",
+ "exit": "^0.1.2",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "istanbul-lib-coverage": "^3.0.0",
+ "istanbul-lib-instrument": "^6.0.0",
+ "istanbul-lib-report": "^3.0.0",
+ "istanbul-lib-source-maps": "^4.0.0",
+ "istanbul-reports": "^3.1.3",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "slash": "^3.0.0",
+ "string-length": "^4.0.1",
+ "strip-ansi": "^6.0.0",
+ "v8-to-istanbul": "^9.0.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.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/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/@jest/reporters/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/@jest/reporters/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/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@sinclair/typebox": "^0.27.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/source-map": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz",
+ "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "callsites": "^3.0.0",
+ "graceful-fs": "^4.2.9"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/test-result": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz",
+ "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/console": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "collect-v8-coverage": "^1.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/test-sequencer": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz",
+ "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/test-result": "^29.7.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/transform": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz",
+ "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@jest/types": "^29.6.3",
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "babel-plugin-istanbul": "^6.1.1",
+ "chalk": "^4.0.0",
+ "convert-source-map": "^2.0.0",
+ "fast-json-stable-stringify": "^2.1.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "pirates": "^4.0.4",
+ "slash": "^3.0.0",
+ "write-file-atomic": "^4.0.2"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.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/remapping": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
+ "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
}
},
"node_modules/@jridgewell/resolve-uri": {
@@ -497,87 +1574,635 @@
"node": ">=6.0.0"
}
},
+ "node_modules/@jridgewell/source-map": {
+ "version": "0.3.11",
+ "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz",
+ "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.25"
+ }
+ },
"node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.5.4",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz",
- "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==",
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
"dev": true,
"license": "MIT"
},
"node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.9",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
- "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
+ "version": "0.3.31",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
+ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jridgewell/resolve-uri": "^3.0.3",
- "@jridgewell/sourcemap-codec": "^1.4.10"
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
}
},
- "node_modules/@redis/bloom": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz",
- "integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==",
- "license": "MIT",
- "peerDependencies": {
- "@redis/client": "^1.0.0"
- }
- },
- "node_modules/@redis/client": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.6.1.tgz",
- "integrity": "sha512-/KCsg3xSlR+nCK8/8ZYSknYxvXHwubJrU82F3Lm1Fp6789VQ0/3RJKfsmRXjqfaTA++23CvC3hqmqe/2GEt6Kw==",
+ "node_modules/@ljharb/through": {
+ "version": "2.3.14",
+ "resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.14.tgz",
+ "integrity": "sha512-ajBvlKpWucBB17FuQYUShqpqy8GRgYEpJW0vWJbUu1CV9lWyrDCapy0lScU8T8Z6qn49sSwJB3+M+evYIdGg+A==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "cluster-key-slot": "1.1.2",
- "generic-pool": "3.9.0",
- "yallist": "4.0.0"
+ "call-bind": "^1.0.8"
},
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/@lukeed/csprng": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz",
+ "integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@nestjs/axios": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-4.0.1.tgz",
+ "integrity": "sha512-68pFJgu+/AZbWkGu65Z3r55bTsCPlgyKaV4BSG8yUAD72q1PPuyVRgUwFv6BxdnibTUHlyxm06FmYWNC+bjN7A==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@nestjs/common": "^10.0.0 || ^11.0.0",
+ "axios": "^1.3.1",
+ "rxjs": "^7.0.0"
+ }
+ },
+ "node_modules/@nestjs/cli": {
+ "version": "10.4.9",
+ "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-10.4.9.tgz",
+ "integrity": "sha512-s8qYd97bggqeK7Op3iD49X2MpFtW4LVNLAwXFkfbRxKME6IYT7X0muNTJ2+QfI8hpbNx9isWkrLWIp+g5FOhiA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@angular-devkit/core": "17.3.11",
+ "@angular-devkit/schematics": "17.3.11",
+ "@angular-devkit/schematics-cli": "17.3.11",
+ "@nestjs/schematics": "^10.0.1",
+ "chalk": "4.1.2",
+ "chokidar": "3.6.0",
+ "cli-table3": "0.6.5",
+ "commander": "4.1.1",
+ "fork-ts-checker-webpack-plugin": "9.0.2",
+ "glob": "10.4.5",
+ "inquirer": "8.2.6",
+ "node-emoji": "1.11.0",
+ "ora": "5.4.1",
+ "tree-kill": "1.2.2",
+ "tsconfig-paths": "4.2.0",
+ "tsconfig-paths-webpack-plugin": "4.2.0",
+ "typescript": "5.7.2",
+ "webpack": "5.97.1",
+ "webpack-node-externals": "3.0.0"
+ },
+ "bin": {
+ "nest": "bin/nest.js"
+ },
+ "engines": {
+ "node": ">= 16.14"
+ },
+ "peerDependencies": {
+ "@swc/cli": "^0.1.62 || ^0.3.0 || ^0.4.0 || ^0.5.0",
+ "@swc/core": "^1.3.62"
+ },
+ "peerDependenciesMeta": {
+ "@swc/cli": {
+ "optional": true
+ },
+ "@swc/core": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@nestjs/cli/node_modules/es-module-lexer": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
+ "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@nestjs/cli/node_modules/eslint-scope": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@nestjs/cli/node_modules/estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/@nestjs/cli/node_modules/typescript": {
+ "version": "5.7.2",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz",
+ "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/@nestjs/cli/node_modules/webpack": {
+ "version": "5.97.1",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.97.1.tgz",
+ "integrity": "sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/eslint-scope": "^3.7.7",
+ "@types/estree": "^1.0.6",
+ "@webassemblyjs/ast": "^1.14.1",
+ "@webassemblyjs/wasm-edit": "^1.14.1",
+ "@webassemblyjs/wasm-parser": "^1.14.1",
+ "acorn": "^8.14.0",
+ "browserslist": "^4.24.0",
+ "chrome-trace-event": "^1.0.2",
+ "enhanced-resolve": "^5.17.1",
+ "es-module-lexer": "^1.2.1",
+ "eslint-scope": "5.1.1",
+ "events": "^3.2.0",
+ "glob-to-regexp": "^0.4.1",
+ "graceful-fs": "^4.2.11",
+ "json-parse-even-better-errors": "^2.3.1",
+ "loader-runner": "^4.2.0",
+ "mime-types": "^2.1.27",
+ "neo-async": "^2.6.2",
+ "schema-utils": "^3.2.0",
+ "tapable": "^2.1.1",
+ "terser-webpack-plugin": "^5.3.10",
+ "watchpack": "^2.4.1",
+ "webpack-sources": "^3.2.3"
+ },
+ "bin": {
+ "webpack": "bin/webpack.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependenciesMeta": {
+ "webpack-cli": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@nestjs/common": {
+ "version": "10.4.22",
+ "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.4.22.tgz",
+ "integrity": "sha512-fxJ4v85nDHaqT1PmfNCQ37b/jcv2OojtXTaK1P2uAXhzLf9qq6WNUOFvxBrV4fhQek1EQoT1o9oj5xAZmv3NRw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "file-type": "20.4.1",
+ "iterare": "1.2.1",
+ "tslib": "2.8.1",
+ "uid": "2.0.2"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/nest"
+ },
+ "peerDependencies": {
+ "class-transformer": "*",
+ "class-validator": "*",
+ "reflect-metadata": "^0.1.12 || ^0.2.0",
+ "rxjs": "^7.1.0"
+ },
+ "peerDependenciesMeta": {
+ "class-transformer": {
+ "optional": true
+ },
+ "class-validator": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@nestjs/config": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-3.3.0.tgz",
+ "integrity": "sha512-pdGTp8m9d0ZCrjTpjkUbZx6gyf2IKf+7zlkrPNMsJzYZ4bFRRTpXrnj+556/5uiI6AfL5mMrJc2u7dB6bvM+VA==",
+ "license": "MIT",
+ "dependencies": {
+ "dotenv": "16.4.5",
+ "dotenv-expand": "10.0.0",
+ "lodash": "4.17.21"
+ },
+ "peerDependencies": {
+ "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0",
+ "rxjs": "^7.1.0"
+ }
+ },
+ "node_modules/@nestjs/core": {
+ "version": "10.4.22",
+ "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.4.22.tgz",
+ "integrity": "sha512-6IX9+VwjiKtCjx+mXVPncpkQ5ZjKfmssOZPFexmT+6T9H9wZ3svpYACAo7+9e7Nr9DZSoRZw3pffkJP7Z0UjaA==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@nuxtjs/opencollective": "0.3.2",
+ "fast-safe-stringify": "2.1.1",
+ "iterare": "1.2.1",
+ "path-to-regexp": "3.3.0",
+ "tslib": "2.8.1",
+ "uid": "2.0.2"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/nest"
+ },
+ "peerDependencies": {
+ "@nestjs/common": "^10.0.0",
+ "@nestjs/microservices": "^10.0.0",
+ "@nestjs/platform-express": "^10.0.0",
+ "@nestjs/websockets": "^10.0.0",
+ "reflect-metadata": "^0.1.12 || ^0.2.0",
+ "rxjs": "^7.1.0"
+ },
+ "peerDependenciesMeta": {
+ "@nestjs/microservices": {
+ "optional": true
+ },
+ "@nestjs/platform-express": {
+ "optional": true
+ },
+ "@nestjs/websockets": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@nestjs/jwt": {
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-10.2.0.tgz",
+ "integrity": "sha512-x8cG90SURkEiLOehNaN2aRlotxT0KZESUliOPKKnjWiyJOcWurkF3w345WOX0P4MgFzUjGoZ1Sy0aZnxeihT0g==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/jsonwebtoken": "9.0.5",
+ "jsonwebtoken": "9.0.2"
+ },
+ "peerDependencies": {
+ "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0"
+ }
+ },
+ "node_modules/@nestjs/mapped-types": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-2.1.0.tgz",
+ "integrity": "sha512-W+n+rM69XsFdwORF11UqJahn4J3xi4g/ZEOlJNL6KoW5ygWSmBB2p0S2BZ4FQeS/NDH72e6xIcu35SfJnE8bXw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@nestjs/common": "^10.0.0 || ^11.0.0",
+ "class-transformer": "^0.4.0 || ^0.5.0",
+ "class-validator": "^0.13.0 || ^0.14.0",
+ "reflect-metadata": "^0.1.12 || ^0.2.0"
+ },
+ "peerDependenciesMeta": {
+ "class-transformer": {
+ "optional": true
+ },
+ "class-validator": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@nestjs/passport": {
+ "version": "10.0.3",
+ "resolved": "https://registry.npmjs.org/@nestjs/passport/-/passport-10.0.3.tgz",
+ "integrity": "sha512-znJ9Y4S8ZDVY+j4doWAJ8EuuVO7SkQN3yOBmzxbGaXbvcSwFDAdGJ+OMCg52NdzIO4tQoN4pYKx8W6M0ArfFRQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0",
+ "passport": "^0.4.0 || ^0.5.0 || ^0.6.0 || ^0.7.0"
+ }
+ },
+ "node_modules/@nestjs/platform-express": {
+ "version": "10.4.22",
+ "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.4.22.tgz",
+ "integrity": "sha512-ySSq7Py/DFozzZdNDH67m/vHoeVdphDniWBnl6q5QVoXldDdrZIHLXLRMPayTDh5A95nt7jjJzmD4qpTbNQ6tA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "body-parser": "1.20.4",
+ "cors": "2.8.5",
+ "express": "4.22.1",
+ "multer": "2.0.2",
+ "tslib": "2.8.1"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/nest"
+ },
+ "peerDependencies": {
+ "@nestjs/common": "^10.0.0",
+ "@nestjs/core": "^10.0.0"
+ }
+ },
+ "node_modules/@nestjs/schematics": {
+ "version": "10.2.3",
+ "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-10.2.3.tgz",
+ "integrity": "sha512-4e8gxaCk7DhBxVUly2PjYL4xC2ifDFexCqq1/u4TtivLGXotVk0wHdYuPYe1tHTHuR1lsOkRbfOCpkdTnigLVg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@angular-devkit/core": "17.3.11",
+ "@angular-devkit/schematics": "17.3.11",
+ "comment-json": "4.2.5",
+ "jsonc-parser": "3.3.1",
+ "pluralize": "8.0.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.2"
+ }
+ },
+ "node_modules/@nestjs/schematics/node_modules/jsonc-parser": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz",
+ "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@nestjs/testing": {
+ "version": "10.4.22",
+ "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.4.22.tgz",
+ "integrity": "sha512-HO9aPus3bAedAC+jKVAA8jTdaj4fs5M9fing4giHrcYV2txe9CvC1l1WAjwQ9RDhEHdugjY4y+FZA/U/YqPZrA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "2.8.1"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/nest"
+ },
+ "peerDependencies": {
+ "@nestjs/common": "^10.0.0",
+ "@nestjs/core": "^10.0.0",
+ "@nestjs/microservices": "^10.0.0",
+ "@nestjs/platform-express": "^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@nestjs/microservices": {
+ "optional": true
+ },
+ "@nestjs/platform-express": {
+ "optional": true
+ }
+ }
+ },
+ "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/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nuxtjs/opencollective": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz",
+ "integrity": "sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==",
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "consola": "^2.15.0",
+ "node-fetch": "^2.6.1"
+ },
+ "bin": {
+ "opencollective": "bin/opencollective.js"
+ },
+ "engines": {
+ "node": ">=8.0.0",
+ "npm": ">=5.0.0"
+ }
+ },
+ "node_modules/@paralleldrive/cuid2": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz",
+ "integrity": "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==",
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
"engines": {
"node": ">=14"
}
},
- "node_modules/@redis/graph": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.1.tgz",
- "integrity": "sha512-FEMTcTHZozZciLRl6GiiIB4zGm5z5F3F6a6FZCyrfxdKOhFlGkiAqlexWMBzCi4DcRoyiOsuLfW+cjlGWyExOw==",
+ "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",
- "peerDependencies": {
- "@redis/client": "^1.0.0"
+ "engines": {
+ "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/pkgr"
}
},
- "node_modules/@redis/json": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.7.tgz",
- "integrity": "sha512-6UyXfjVaTBTJtKNG4/9Z8PSpKE6XgSyEb8iwaqDcy+uKrd/DGYHTWkUdnQDyzm727V7p21WUMhsqz5oy65kPcQ==",
- "license": "MIT",
+ "node_modules/@prisma/client": {
+ "version": "5.22.0",
+ "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.22.0.tgz",
+ "integrity": "sha512-M0SVXfyHnQREBKxCgyo7sffrKttwE6R8PMq330MIUF0pTwjUhLbW84pFDlf06B27XyCR++VtjugEnIHdr07SVA==",
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "peer": true,
+ "engines": {
+ "node": ">=16.13"
+ },
"peerDependencies": {
- "@redis/client": "^1.0.0"
+ "prisma": "*"
+ },
+ "peerDependenciesMeta": {
+ "prisma": {
+ "optional": true
+ }
}
},
- "node_modules/@redis/search": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.2.0.tgz",
- "integrity": "sha512-tYoDBbtqOVigEDMAcTGsRlMycIIjwMCgD8eR2t0NANeQmgK/lvxNAvYyb6bZDD4frHRhIHkJu2TBRvB0ERkOmw==",
- "license": "MIT",
- "peerDependencies": {
- "@redis/client": "^1.0.0"
+ "node_modules/@prisma/debug": {
+ "version": "5.22.0",
+ "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.22.0.tgz",
+ "integrity": "sha512-AUt44v3YJeggO2ZU5BkXI7M4hu9BF2zzH2iF2V5pyXT/lRTyWiElZ7It+bRH1EshoMRxHgpYg4VB6rCM+mG5jQ==",
+ "devOptional": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/@prisma/engines": {
+ "version": "5.22.0",
+ "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.22.0.tgz",
+ "integrity": "sha512-UNjfslWhAt06kVL3CjkuYpHAWSO6L4kDCVPegV6itt7nD1kSJavd3vhgAEhjglLJJKEdJ7oIqDJ+yHk6qO8gPA==",
+ "devOptional": true,
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@prisma/debug": "5.22.0",
+ "@prisma/engines-version": "5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2",
+ "@prisma/fetch-engine": "5.22.0",
+ "@prisma/get-platform": "5.22.0"
}
},
- "node_modules/@redis/time-series": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.1.0.tgz",
- "integrity": "sha512-c1Q99M5ljsIuc4YdaCwfUEXsofakb9c8+Zse2qxTadu8TalLXuAESzLvFAvNVbkmSlvlzIQOLpBCmWI9wTOt+g==",
- "license": "MIT",
- "peerDependencies": {
- "@redis/client": "^1.0.0"
+ "node_modules/@prisma/engines-version": {
+ "version": "5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2",
+ "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2.tgz",
+ "integrity": "sha512-2PTmxFR2yHW/eB3uqWtcgRcgAbG1rwG9ZriSvQw+nnb7c4uCr3RAcGMb6/zfE88SKlC1Nj2ziUvc96Z379mHgQ==",
+ "devOptional": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/@prisma/fetch-engine": {
+ "version": "5.22.0",
+ "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.22.0.tgz",
+ "integrity": "sha512-bkrD/Mc2fSvkQBV5EpoFcZ87AvOgDxbG99488a5cexp5Ccny+UM6MAe/UFkUC0wLYD9+9befNOqGiIJhhq+HbA==",
+ "devOptional": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@prisma/debug": "5.22.0",
+ "@prisma/engines-version": "5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2",
+ "@prisma/get-platform": "5.22.0"
}
},
+ "node_modules/@prisma/get-platform": {
+ "version": "5.22.0",
+ "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.22.0.tgz",
+ "integrity": "sha512-pHhpQdr1UPFpt+zFfnPazhulaZYCUqeIcPpJViYoq9R+D/yw4fjE+CtnsnKzPYm0ddUbeXUzjGVGIRVgPDCk4Q==",
+ "devOptional": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@prisma/debug": "5.22.0"
+ }
+ },
+ "node_modules/@sinclair/typebox": {
+ "version": "0.27.8",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
+ "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==",
+ "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": "10.3.0",
+ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz",
+ "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@sinonjs/commons": "^3.0.0"
+ }
+ },
+ "node_modules/@tokenizer/inflate": {
+ "version": "0.2.7",
+ "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.2.7.tgz",
+ "integrity": "sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.4.0",
+ "fflate": "^0.8.2",
+ "token-types": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Borewit"
+ }
+ },
+ "node_modules/@tokenizer/token": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz",
+ "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==",
+ "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==",
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz",
+ "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==",
"dev": true,
"license": "MIT"
},
@@ -602,6 +2227,51 @@
"dev": true,
"license": "MIT"
},
+ "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/body-parser": {
"version": "1.19.6",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz",
@@ -623,33 +2293,60 @@
"@types/node": "*"
}
},
- "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==",
+ "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/eslint": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz",
+ "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/estree": "*",
+ "@types/json-schema": "*"
+ }
+ },
+ "node_modules/@types/eslint-scope": {
+ "version": "3.7.7",
+ "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz",
+ "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@types/node": "*"
+ "@types/eslint": "*",
+ "@types/estree": "*"
}
},
+ "node_modules/@types/estree": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/express": {
- "version": "4.17.23",
- "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.23.tgz",
- "integrity": "sha512-Crp6WY9aTYP3qPi2wGDo9iUe/rceX01UMhnF1jmwDcKCFM6cx7YhGP/Mpr3y9AASpfHixIG0E6azCcL5OcDHsQ==",
+ "version": "4.17.25",
+ "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz",
+ "integrity": "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/body-parser": "*",
"@types/express-serve-static-core": "^4.17.33",
"@types/qs": "*",
- "@types/serve-static": "*"
+ "@types/serve-static": "^1"
}
},
"node_modules/@types/express-serve-static-core": {
- "version": "4.19.6",
- "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz",
- "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==",
+ "version": "4.19.8",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz",
+ "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -659,6 +2356,16 @@
"@types/send": "*"
}
},
+ "node_modules/@types/graceful-fs": {
+ "version": "4.1.9",
+ "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz",
+ "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/http-errors": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz",
@@ -666,17 +2373,67 @@
"dev": true,
"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==",
+ "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/ms": "*",
+ "@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": "29.5.14",
+ "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz",
+ "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "expect": "^29.0.0",
+ "pretty-format": "^29.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==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/jsonwebtoken": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.5.tgz",
+ "integrity": "sha512-VRLSGzik+Unrup6BsouBeHsf4d1hOEgYWTm/7Nmw1sXoN1+tRly/Gy/po3yeahnP4jfnQWWAhQAqcNfH7ngOkA==",
+ "license": "MIT",
+ "dependencies": {
"@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",
@@ -684,33 +2441,46 @@
"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/node": {
- "version": "20.19.9",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.9.tgz",
- "integrity": "sha512-cuVNgarYWZqxRJDQHEB58GEONhOK79QVR/qYx4S7kcUObQvUwvFnYxJuuHUKm2aieN9X3yZB4LZsuYNU1Qphsw==",
- "dev": true,
+ "version": "20.19.30",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz",
+ "integrity": "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"undici-types": "~6.21.0"
}
},
- "node_modules/@types/pg": {
- "version": "8.15.4",
- "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.15.4.tgz",
- "integrity": "sha512-I6UNVBAoYbvuWkkU3oosC8yxqH21f4/Jc4DK71JLG3dT2mdlGe1z+ep/LQGXaKaOgcvUrsQoPRqfgtMcvZiJhg==",
+ "node_modules/@types/passport": {
+ "version": "1.0.17",
+ "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.17.tgz",
+ "integrity": "sha512-aciLyx+wDwT2t2/kJGJR2AEeBz0nJU4WuRX04Wu9Dqc5lSUtwu0WERPHYsLhF9PtseiAMPBGNUOtFjxZ56prsg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@types/node": "*",
- "pg-protocol": "*",
- "pg-types": "^2.2.0"
+ "@types/express": "*"
+ }
+ },
+ "node_modules/@types/passport-jwt": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@types/passport-jwt/-/passport-jwt-4.0.1.tgz",
+ "integrity": "sha512-Y0Ykz6nWP4jpxgEUYq8NoVZeCQPo1ZndJLfapI249g1jHChvRfZRO/LS3tqu26YgAS/laI1qx98sYGz0IalRXQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/jsonwebtoken": "*",
+ "@types/passport-strategy": "*"
+ }
+ },
+ "node_modules/@types/passport-strategy": {
+ "version": "0.2.38",
+ "resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.38.tgz",
+ "integrity": "sha512-GC6eMqqojOooq993Tmnmp7AUTbbQSgilyvpCYQjT+H6JfG/g6RGc7nXEniZlp0zyKJ0WUdOiZWLBZft9Yug1uA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/express": "*",
+ "@types/passport": "*"
}
},
"node_modules/@types/qs": {
@@ -727,10 +2497,39 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@types/semver": {
+ "version": "7.7.1",
+ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz",
+ "integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==",
+ "dev": true,
+ "license": "MIT"
+ },
"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==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz",
+ "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/serve-static": {
+ "version": "1.15.10",
+ "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz",
+ "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/http-errors": "*",
+ "@types/node": "*",
+ "@types/send": "<1"
+ }
+ },
+ "node_modules/@types/serve-static/node_modules/@types/send": {
+ "version": "0.17.6",
+ "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz",
+ "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -738,39 +2537,476 @@
"@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==",
+ "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/http-errors": "*",
+ "@types/cookiejar": "^2.1.5",
+ "@types/methods": "^1.1.4",
"@types/node": "*",
- "@types/send": "*"
+ "form-data": "^4.0.0"
}
},
- "node_modules/@types/strip-bom": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz",
- "integrity": "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==",
+ "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/validator": {
+ "version": "13.15.10",
+ "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.10.tgz",
+ "integrity": "sha512-T8L6i7wCuyoK8A/ZeLYt1+q0ty3Zb9+qbSSvrIVitzT3YjZqkTZ40IbRsPanlB4h1QB3JVL1SYCdR6ngtFYcuA==",
+ "license": "MIT"
+ },
+ "node_modules/@types/yargs": {
+ "version": "17.0.35",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz",
+ "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==",
+ "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/@types/strip-json-comments": {
- "version": "0.0.30",
- "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz",
- "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==",
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz",
+ "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.5.1",
+ "@typescript-eslint/scope-manager": "6.21.0",
+ "@typescript-eslint/type-utils": "6.21.0",
+ "@typescript-eslint/utils": "6.21.0",
+ "@typescript-eslint/visitor-keys": "6.21.0",
+ "debug": "^4.3.4",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.4",
+ "natural-compare": "^1.4.0",
+ "semver": "^7.5.4",
+ "ts-api-utils": "^1.0.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha",
+ "eslint": "^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz",
+ "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "peer": true,
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "6.21.0",
+ "@typescript-eslint/types": "6.21.0",
+ "@typescript-eslint/typescript-estree": "6.21.0",
+ "@typescript-eslint/visitor-keys": "6.21.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz",
+ "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "6.21.0",
+ "@typescript-eslint/visitor-keys": "6.21.0"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz",
+ "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/typescript-estree": "6.21.0",
+ "@typescript-eslint/utils": "6.21.0",
+ "debug": "^4.3.4",
+ "ts-api-utils": "^1.0.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz",
+ "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz",
+ "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "@typescript-eslint/types": "6.21.0",
+ "@typescript-eslint/visitor-keys": "6.21.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "minimatch": "9.0.3",
+ "semver": "^7.5.4",
+ "ts-api-utils": "^1.0.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/utils": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz",
+ "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.4.0",
+ "@types/json-schema": "^7.0.12",
+ "@types/semver": "^7.5.0",
+ "@typescript-eslint/scope-manager": "6.21.0",
+ "@typescript-eslint/types": "6.21.0",
+ "@typescript-eslint/typescript-estree": "6.21.0",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz",
+ "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "6.21.0",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@ucast/core": {
+ "version": "1.10.2",
+ "resolved": "https://registry.npmjs.org/@ucast/core/-/core-1.10.2.tgz",
+ "integrity": "sha512-ons5CwXZ/51wrUPfoduC+cO7AS1/wRb0ybpQJ9RrssossDxVy4t49QxWoWgfBDvVKsz9VXzBk9z0wqTdZ+Cq8g==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@ucast/js": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@ucast/js/-/js-3.0.4.tgz",
+ "integrity": "sha512-TgG1aIaCMdcaEyckOZKQozn1hazE0w90SVdlpIJ/er8xVumE11gYAtSbw/LBeUnA4fFnFWTcw3t6reqseeH/4Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@ucast/core": "^1.0.0"
+ }
+ },
+ "node_modules/@ucast/mongo": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/@ucast/mongo/-/mongo-2.4.3.tgz",
+ "integrity": "sha512-XcI8LclrHWP83H+7H2anGCEeDq0n+12FU2mXCTz6/Tva9/9ddK/iacvvhCyW6cijAAOILmt0tWplRyRhVyZLsA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@ucast/core": "^1.4.1"
+ }
+ },
+ "node_modules/@ucast/mongo2js": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@ucast/mongo2js/-/mongo2js-1.4.0.tgz",
+ "integrity": "sha512-vR9RJ3BHlkI3RfKJIZFdVktxWvBCQRiSTeJSWN9NPxP5YJkpfXvcBWAMLwvyJx4HbB+qib5/AlSDEmQiuQyx2w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@ucast/core": "^1.6.1",
+ "@ucast/js": "^3.0.0",
+ "@ucast/mongo": "^2.4.0"
+ }
+ },
+ "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/@webassemblyjs/ast": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz",
+ "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@webassemblyjs/helper-numbers": "1.13.2",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2"
+ }
+ },
+ "node_modules/@webassemblyjs/floating-point-hex-parser": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz",
+ "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==",
"dev": true,
"license": "MIT"
},
- "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==",
+ "node_modules/@webassemblyjs/helper-api-error": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz",
+ "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==",
"dev": true,
"license": "MIT"
},
+ "node_modules/@webassemblyjs/helper-buffer": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz",
+ "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@webassemblyjs/helper-numbers": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz",
+ "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@webassemblyjs/floating-point-hex-parser": "1.13.2",
+ "@webassemblyjs/helper-api-error": "1.13.2",
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "node_modules/@webassemblyjs/helper-wasm-bytecode": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz",
+ "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@webassemblyjs/helper-wasm-section": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz",
+ "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-buffer": "1.14.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/wasm-gen": "1.14.1"
+ }
+ },
+ "node_modules/@webassemblyjs/ieee754": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz",
+ "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@xtuc/ieee754": "^1.2.0"
+ }
+ },
+ "node_modules/@webassemblyjs/leb128": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz",
+ "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "node_modules/@webassemblyjs/utf8": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz",
+ "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@webassemblyjs/wasm-edit": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz",
+ "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-buffer": "1.14.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/helper-wasm-section": "1.14.1",
+ "@webassemblyjs/wasm-gen": "1.14.1",
+ "@webassemblyjs/wasm-opt": "1.14.1",
+ "@webassemblyjs/wasm-parser": "1.14.1",
+ "@webassemblyjs/wast-printer": "1.14.1"
+ }
+ },
+ "node_modules/@webassemblyjs/wasm-gen": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz",
+ "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/ieee754": "1.13.2",
+ "@webassemblyjs/leb128": "1.13.2",
+ "@webassemblyjs/utf8": "1.13.2"
+ }
+ },
+ "node_modules/@webassemblyjs/wasm-opt": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz",
+ "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-buffer": "1.14.1",
+ "@webassemblyjs/wasm-gen": "1.14.1",
+ "@webassemblyjs/wasm-parser": "1.14.1"
+ }
+ },
+ "node_modules/@webassemblyjs/wasm-parser": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz",
+ "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-api-error": "1.13.2",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/ieee754": "1.13.2",
+ "@webassemblyjs/leb128": "1.13.2",
+ "@webassemblyjs/utf8": "1.13.2"
+ }
+ },
+ "node_modules/@webassemblyjs/wast-printer": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz",
+ "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@webassemblyjs/ast": "1.14.1",
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "node_modules/@xtuc/ieee754": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
+ "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@xtuc/long": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
+ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
+ "dev": true,
+ "license": "Apache-2.0"
+ },
"node_modules/accepts": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
@@ -790,6 +3026,7 @@
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
"license": "MIT",
+ "peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -797,6 +3034,29 @@
"node": ">=0.4.0"
}
},
+ "node_modules/acorn-import-phases": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz",
+ "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "peerDependencies": {
+ "acorn": "^8.14.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
"node_modules/acorn-walk": {
"version": "8.3.4",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
@@ -810,13 +3070,117 @@
"node": ">=0.4.0"
}
},
- "node_modules/agent-base": {
- "version": "7.1.4",
- "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
- "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
+ "node_modules/ajv": {
+ "version": "8.12.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
+ "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ajv-formats": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
+ "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "ajv": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/ajv-keywords": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
+ "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3"
+ },
+ "peerDependencies": {
+ "ajv": "^8.8.2"
+ }
+ },
+ "node_modules/ansi-colors": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
+ "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
+ "dev": true,
"license": "MIT",
"engines": {
- "node": ">= 14"
+ "node": ">=6"
+ }
+ },
+ "node_modules/ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "type-fest": "^0.21.3"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-escapes/node_modules/type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "dev": true,
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/anymatch": {
@@ -833,6 +3197,25 @@
"node": ">= 8"
}
},
+ "node_modules/anymatch/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/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",
@@ -840,12 +3223,187 @@
"dev": 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==",
+ "dev": true,
+ "license": "Python-2.0"
+ },
"node_modules/array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
"license": "MIT"
},
+ "node_modules/array-timsort": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz",
+ "integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "license": "MIT"
+ },
+ "node_modules/axios": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz",
+ "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.4",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
+ "node_modules/babel-jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
+ "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/transform": "^29.7.0",
+ "@types/babel__core": "^7.1.14",
+ "babel-plugin-istanbul": "^6.1.1",
+ "babel-preset-jest": "^29.6.3",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.8.0"
+ }
+ },
+ "node_modules/babel-plugin-istanbul": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz",
+ "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==",
+ "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.2",
+ "istanbul-lib-instrument": "^5.0.4",
+ "test-exclude": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz",
+ "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/core": "^7.12.3",
+ "@babel/parser": "^7.14.7",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-coverage": "^3.2.0",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/babel-plugin-istanbul/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-plugin-jest-hoist": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz",
+ "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.3.3",
+ "@babel/types": "^7.3.3",
+ "@types/babel__core": "^7.1.14",
+ "@types/babel__traverse": "^7.0.6"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.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": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz",
+ "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "babel-plugin-jest-hoist": "^29.6.3",
+ "babel-preset-current-node-syntax": "^1.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -857,6 +3415,7 @@
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "dev": true,
"funding": [
{
"type": "github",
@@ -873,13 +3432,14 @@
],
"license": "MIT"
},
- "node_modules/bignumber.js": {
- "version": "9.3.1",
- "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz",
- "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==",
- "license": "MIT",
- "engines": {
- "node": "*"
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.9.18",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.18.tgz",
+ "integrity": "sha512-e23vBV1ZLfjb9apvfPk4rHVu2ry6RIr2Wfs+O324okSidrX7pTAnEJPCh/O5BtRlr7QtZI7ktOP3vsqr7Z5XoA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.js"
}
},
"node_modules/binary-extensions": {
@@ -895,39 +3455,65 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/body-parser": {
- "version": "1.20.3",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
- "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
+ "node_modules/bl": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+ "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "bytes": "3.1.2",
+ "buffer": "^5.5.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.4.0"
+ }
+ },
+ "node_modules/body-parser": {
+ "version": "1.20.4",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz",
+ "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==",
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "~3.1.2",
"content-type": "~1.0.5",
"debug": "2.6.9",
"depd": "2.0.0",
- "destroy": "1.2.0",
- "http-errors": "2.0.0",
- "iconv-lite": "0.4.24",
- "on-finished": "2.4.1",
- "qs": "6.13.0",
- "raw-body": "2.5.2",
+ "destroy": "~1.2.0",
+ "http-errors": "~2.0.1",
+ "iconv-lite": "~0.4.24",
+ "on-finished": "~2.4.1",
+ "qs": "~6.14.0",
+ "raw-body": "~2.5.3",
"type-is": "~1.6.18",
- "unpipe": "1.0.0"
+ "unpipe": "~1.0.0"
},
"engines": {
"node": ">= 0.8",
"npm": "1.2.8000 || >= 1.4.16"
}
},
+ "node_modules/body-parser/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/body-parser/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT"
+ },
"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==",
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
+ "balanced-match": "^1.0.0"
}
},
"node_modules/braces": {
@@ -943,6 +3529,89 @@
"node": ">=8"
}
},
+ "node_modules/browserslist": {
+ "version": "4.28.1",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz",
+ "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "baseline-browser-mapping": "^2.9.0",
+ "caniuse-lite": "^1.0.30001759",
+ "electron-to-chromium": "^1.5.263",
+ "node-releases": "^2.0.27",
+ "update-browserslist-db": "^1.2.0"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "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": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
"node_modules/buffer-equal-constant-time": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
@@ -953,9 +3622,19 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
- "dev": true,
"license": "MIT"
},
+ "node_modules/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",
@@ -965,6 +3644,25 @@
"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==",
+ "dev": true,
+ "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",
@@ -994,6 +3692,80 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/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.30001766",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001766.tgz",
+ "integrity": "sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA==",
+ "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==",
+ "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/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/chardet": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
+ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/chokidar": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
@@ -1019,6 +3791,153 @@
"fsevents": "~2.3.2"
}
},
+ "node_modules/chrome-trace-event": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz",
+ "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0"
+ }
+ },
+ "node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cjs-module-lexer": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz",
+ "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/class-transformer": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz",
+ "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/class-validator": {
+ "version": "0.14.3",
+ "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.3.tgz",
+ "integrity": "sha512-rXXekcjofVN1LTOSw+u4u9WXVEUvNBVjORW154q/IdmYWy1nMbOU9aNtZB0t8m+FJQ9q91jlr2f9CwwUFdFMRA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/validator": "^13.15.3",
+ "libphonenumber-js": "^1.11.1",
+ "validator": "^13.15.20"
+ }
+ },
+ "node_modules/cli-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+ "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "restore-cursor": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cli-spinners": {
+ "version": "2.9.2",
+ "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz",
+ "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cli-table3": {
+ "version": "0.6.5",
+ "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz",
+ "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "string-width": "^4.2.0"
+ },
+ "engines": {
+ "node": "10.* || >= 12.*"
+ },
+ "optionalDependencies": {
+ "@colors/colors": "1.5.0"
+ }
+ },
+ "node_modules/cli-width": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz",
+ "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/cliui/node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/clone": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
+ "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
"node_modules/cluster-key-slot": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz",
@@ -1028,6 +3947,91 @@
"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.3",
+ "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz",
+ "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "license": "MIT",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/commander": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
+ "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/comment-json": {
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-4.2.5.tgz",
+ "integrity": "sha512-bKw/r35jR3HGt5PEPm1ljsQQGyCrR8sFGNiN5L+ykDHdpO8Smxkrkla9Yi6NkQyUrb8V54PGhfMs6NrIwtxtdw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-timsort": "^1.0.3",
+ "core-util-is": "^1.0.3",
+ "esprima": "^4.0.1",
+ "has-own-prop": "^2.0.0",
+ "repeat-string": "^1.6.1"
+ },
+ "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",
@@ -1035,6 +4039,27 @@
"dev": true,
"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/consola": {
+ "version": "2.15.3",
+ "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz",
+ "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==",
+ "license": "MIT"
+ },
"node_modules/content-disposition": {
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
@@ -1056,19 +4081,40 @@
"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.1",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
- "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
+ "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-signature": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
- "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz",
+ "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==",
+ "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/core-util-is": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
+ "dev": true,
"license": "MIT"
},
"node_modules/cors": {
@@ -1084,6 +4130,55 @@
"node": ">= 0.10"
}
},
+ "node_modules/cosmiconfig": {
+ "version": "8.3.6",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz",
+ "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "import-fresh": "^3.3.0",
+ "js-yaml": "^4.1.0",
+ "parse-json": "^5.2.0",
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/d-fischer"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.9.5"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/create-jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz",
+ "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.9",
+ "jest-config": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "prompts": "^2.0.1"
+ },
+ "bin": {
+ "create-jest": "bin/create-jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
"node_modules/create-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
@@ -1091,22 +4186,117 @@
"dev": true,
"license": "MIT"
},
- "node_modules/data-uri-to-buffer": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
- "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dev": true,
"license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
"engines": {
- "node": ">= 12"
+ "node": ">= 8"
}
},
"node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"license": "MIT",
"dependencies": {
- "ms": "2.0.0"
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/dedent": {
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.1.tgz",
+ "integrity": "sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "babel-plugin-macros": "^3.1.0"
+ },
+ "peerDependenciesMeta": {
+ "babel-plugin-macros": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/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/defaults": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
+ "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "clone": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/define-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==",
+ "dev": true,
+ "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==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/denque": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
+ "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=0.10"
}
},
"node_modules/depd": {
@@ -1128,20 +4318,77 @@
"npm": "1.2.8000 || >= 1.4.16"
}
},
+ "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==",
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz",
+ "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.3.1"
}
},
+ "node_modules/diff-sequences": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz",
+ "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "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==",
+ "version": "16.4.5",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
+ "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==",
"license": "BSD-2-Clause",
"engines": {
"node": ">=12"
@@ -1150,6 +4397,15 @@
"url": "https://dotenvx.com"
}
},
+ "node_modules/dotenv-expand": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz",
+ "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
@@ -1164,15 +4420,12 @@
"node": ">= 0.4"
}
},
- "node_modules/dynamic-dedupe": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz",
- "integrity": "sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ==",
+ "node_modules/eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
"dev": true,
- "license": "MIT",
- "dependencies": {
- "xtend": "^4.0.0"
- }
+ "license": "MIT"
},
"node_modules/ecdsa-sig-formatter": {
"version": "1.0.11",
@@ -1189,6 +4442,33 @@
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
"license": "MIT"
},
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.278",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.278.tgz",
+ "integrity": "sha512-dQ0tM1svDRQOwxnXxm+twlGTjr9Upvt8UFWAgmLsxEzFQxhbti4VwxmMjsDxVC51Zo84swW7FVCXEV+VAkhuPw==",
+ "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": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/encodeurl": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
@@ -1198,6 +4478,30 @@
"node": ">= 0.8"
}
},
+ "node_modules/enhanced-resolve": {
+ "version": "5.18.4",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.4.tgz",
+ "integrity": "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.4",
+ "tapable": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/error-ex": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz",
+ "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
"node_modules/es-define-property": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
@@ -1216,6 +4520,13 @@
"node": ">= 0.4"
}
},
+ "node_modules/es-module-lexer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz",
+ "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/es-object-atoms": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
@@ -1228,46 +4539,29 @@
"node": ">= 0.4"
}
},
- "node_modules/esbuild": {
- "version": "0.25.8",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.8.tgz",
- "integrity": "sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q==",
- "dev": true,
- "hasInstallScript": true,
+ "node_modules/es-set-tostringtag": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
"license": "MIT",
- "bin": {
- "esbuild": "bin/esbuild"
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
},
"engines": {
- "node": ">=18"
- },
- "optionalDependencies": {
- "@esbuild/aix-ppc64": "0.25.8",
- "@esbuild/android-arm": "0.25.8",
- "@esbuild/android-arm64": "0.25.8",
- "@esbuild/android-x64": "0.25.8",
- "@esbuild/darwin-arm64": "0.25.8",
- "@esbuild/darwin-x64": "0.25.8",
- "@esbuild/freebsd-arm64": "0.25.8",
- "@esbuild/freebsd-x64": "0.25.8",
- "@esbuild/linux-arm": "0.25.8",
- "@esbuild/linux-arm64": "0.25.8",
- "@esbuild/linux-ia32": "0.25.8",
- "@esbuild/linux-loong64": "0.25.8",
- "@esbuild/linux-mips64el": "0.25.8",
- "@esbuild/linux-ppc64": "0.25.8",
- "@esbuild/linux-riscv64": "0.25.8",
- "@esbuild/linux-s390x": "0.25.8",
- "@esbuild/linux-x64": "0.25.8",
- "@esbuild/netbsd-arm64": "0.25.8",
- "@esbuild/netbsd-x64": "0.25.8",
- "@esbuild/openbsd-arm64": "0.25.8",
- "@esbuild/openbsd-x64": "0.25.8",
- "@esbuild/openharmony-arm64": "0.25.8",
- "@esbuild/sunos-x64": "0.25.8",
- "@esbuild/win32-arm64": "0.25.8",
- "@esbuild/win32-ia32": "0.25.8",
- "@esbuild/win32-x64": "0.25.8"
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
}
},
"node_modules/escape-html": {
@@ -1276,6 +4570,291 @@
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
"license": "MIT"
},
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "8.57.1",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz",
+ "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==",
+ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.6.1",
+ "@eslint/eslintrc": "^2.1.4",
+ "@eslint/js": "8.57.1",
+ "@humanwhocodes/config-array": "^0.13.0",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@nodelib/fs.walk": "^1.2.8",
+ "@ungap/structured-clone": "^1.2.0",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.2.2",
+ "eslint-visitor-keys": "^3.4.3",
+ "espree": "^9.6.1",
+ "esquery": "^1.4.2",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "globals": "^13.19.0",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "is-path-inside": "^3.0.3",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3",
+ "strip-ansi": "^6.0.1",
+ "text-table": "^0.2.0"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-config-prettier": {
+ "version": "9.1.2",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.2.tgz",
+ "integrity": "sha512-iI1f+D2ViGn+uvv5HuHVUamg8ll4tN+JRHGc6IJi4TP9Kl976C57fzPXgseXNs8v0iA8aSJpHsTWjDb9QJamGQ==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "bin": {
+ "eslint-config-prettier": "bin/cli.js"
+ },
+ "peerDependencies": {
+ "eslint": ">=7.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-prettier": {
+ "version": "5.5.5",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.5.tgz",
+ "integrity": "sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prettier-linter-helpers": "^1.0.1",
+ "synckit": "^0.11.12"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint-plugin-prettier"
+ },
+ "peerDependencies": {
+ "@types/eslint": ">=8.0.0",
+ "eslint": ">=8.0.0",
+ "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0",
+ "prettier": ">=3.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/eslint": {
+ "optional": true
+ },
+ "eslint-config-prettier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
+ "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/eslint/node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/eslint/node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/eslint/node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/eslint/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/espree": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
+ "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "acorn": "^8.9.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "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/esquery": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz",
+ "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/etag": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
@@ -1285,40 +4864,107 @@
"node": ">= 0.6"
}
},
+ "node_modules/events": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.x"
+ }
+ },
+ "node_modules/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": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+ "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/expect": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz",
+ "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/expect-utils": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
"node_modules/express": {
- "version": "4.21.2",
- "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
- "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==",
+ "version": "4.22.1",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz",
+ "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==",
"license": "MIT",
"dependencies": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
- "body-parser": "1.20.3",
- "content-disposition": "0.5.4",
+ "body-parser": "~1.20.3",
+ "content-disposition": "~0.5.4",
"content-type": "~1.0.4",
- "cookie": "0.7.1",
- "cookie-signature": "1.0.6",
+ "cookie": "~0.7.1",
+ "cookie-signature": "~1.0.6",
"debug": "2.6.9",
"depd": "2.0.0",
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
- "finalhandler": "1.3.1",
- "fresh": "0.5.2",
- "http-errors": "2.0.0",
+ "finalhandler": "~1.3.1",
+ "fresh": "~0.5.2",
+ "http-errors": "~2.0.0",
"merge-descriptors": "1.0.3",
"methods": "~1.1.2",
- "on-finished": "2.4.1",
+ "on-finished": "~2.4.1",
"parseurl": "~1.3.3",
- "path-to-regexp": "0.1.12",
+ "path-to-regexp": "~0.1.12",
"proxy-addr": "~2.0.7",
- "qs": "6.13.0",
+ "qs": "~6.14.0",
"range-parser": "~1.2.1",
"safe-buffer": "5.2.1",
- "send": "0.19.0",
- "serve-static": "1.16.2",
+ "send": "~0.19.0",
+ "serve-static": "~1.16.2",
"setprototypeof": "1.2.0",
- "statuses": "2.0.1",
+ "statuses": "~2.0.1",
"type-is": "~1.6.18",
"utils-merge": "1.0.1",
"vary": "~1.1.2"
@@ -1331,33 +4977,174 @@
"url": "https://opencollective.com/express"
}
},
- "node_modules/extend": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
- "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
- "license": "MIT"
- },
- "node_modules/fetch-blob": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
- "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/jimmywarting"
- },
- {
- "type": "paypal",
- "url": "https://paypal.me/jimmywarting"
- }
- ],
+ "node_modules/express/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"license": "MIT",
"dependencies": {
- "node-domexception": "^1.0.0",
- "web-streams-polyfill": "^3.0.3"
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/express/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT"
+ },
+ "node_modules/express/node_modules/path-to-regexp": {
+ "version": "0.1.12",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
+ "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==",
+ "license": "MIT"
+ },
+ "node_modules/external-editor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
+ "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chardet": "^0.7.0",
+ "iconv-lite": "^0.4.24",
+ "tmp": "^0.0.33"
},
"engines": {
- "node": "^12.20 || >= 14.13"
+ "node": ">=4"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-diff": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
+ "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==",
+ "dev": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
+ "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.8"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/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==",
+ "license": "MIT"
+ },
+ "node_modules/fastq": {
+ "version": "1.20.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
+ "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "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/fflate": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz",
+ "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==",
+ "license": "MIT"
+ },
+ "node_modules/figures": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
+ "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "escape-string-regexp": "^1.0.5"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/figures/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flat-cache": "^3.0.4"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/file-type": {
+ "version": "20.4.1",
+ "resolved": "https://registry.npmjs.org/file-type/-/file-type-20.4.1.tgz",
+ "integrity": "sha512-hw9gNZXUfZ02Jo0uafWLaFVPter5/k2rfcrjFJJHX/77xtSDOfJuEFb6oKlFV86FLP1SuyHMW1PSk0U9M5tKkQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@tokenizer/inflate": "^0.2.6",
+ "strtok3": "^10.2.0",
+ "token-types": "^6.0.0",
+ "uint8array-extras": "^1.4.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/file-type?sponsor=1"
}
},
"node_modules/fill-range": {
@@ -1374,33 +5161,197 @@
}
},
"node_modules/finalhandler": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz",
- "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==",
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz",
+ "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==",
"license": "MIT",
"dependencies": {
"debug": "2.6.9",
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
- "on-finished": "2.4.1",
+ "on-finished": "~2.4.1",
"parseurl": "~1.3.3",
- "statuses": "2.0.1",
+ "statuses": "~2.0.2",
"unpipe": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
- "node_modules/formdata-polyfill": {
- "version": "4.0.10",
- "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
- "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
+ "node_modules/finalhandler/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"license": "MIT",
"dependencies": {
- "fetch-blob": "^3.1.2"
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/finalhandler/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT"
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
},
"engines": {
- "node": ">=12.20.0"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
+ "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.3",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
+ "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/follow-redirects": {
+ "version": "1.15.11",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
+ "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/foreground-child": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
+ "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "cross-spawn": "^7.0.6",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/fork-ts-checker-webpack-plugin": {
+ "version": "9.0.2",
+ "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-9.0.2.tgz",
+ "integrity": "sha512-Uochze2R8peoN1XqlSi/rGUkDQpRogtLFocP9+PGu68zk1BDAKXfdeCdyVZpgTk8V8WFVQXdEz426VKjXLO1Gg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.16.7",
+ "chalk": "^4.1.2",
+ "chokidar": "^3.5.3",
+ "cosmiconfig": "^8.2.0",
+ "deepmerge": "^4.2.2",
+ "fs-extra": "^10.0.0",
+ "memfs": "^3.4.1",
+ "minimatch": "^3.0.4",
+ "node-abort-controller": "^3.0.1",
+ "schema-utils": "^3.1.1",
+ "semver": "^7.3.5",
+ "tapable": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=12.13.0",
+ "yarn": ">=1.0.0"
+ },
+ "peerDependencies": {
+ "typescript": ">3.6.0",
+ "webpack": "^5.11.0"
+ }
+ },
+ "node_modules/fork-ts-checker-webpack-plugin/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/fork-ts-checker-webpack-plugin/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/form-data": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
+ "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
+ "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/formidable": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.5.tgz",
+ "integrity": "sha512-Oz5Hwvwak/DCaXVVUtPn4oLMLLy1CdclLKO1LFgU7XzDpVMUU5UjlSLpGMocyQNNk8F6IJW9M/YdooSn2MRI+Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@paralleldrive/cuid2": "^2.2.2",
+ "dezalgo": "^1.0.4",
+ "once": "^1.4.0",
+ "qs": "^6.11.0"
+ },
+ "funding": {
+ "url": "https://ko-fi.com/tunnckoCore/commissions"
}
},
"node_modules/forwarded": {
@@ -1421,6 +5372,28 @@
"node": ">= 0.6"
}
},
+ "node_modules/fs-extra": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
+ "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/fs-monkey": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.1.0.tgz",
+ "integrity": "sha512-QMUezzXWII9EV5aTFXW1UBVUO77wYPpjqIF8/AviUCThNeSYZykpoTixUeaNNBwmCev0AMDWMAni+f8Hxb1IFw==",
+ "dev": true,
+ "license": "Unlicense"
+ },
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@@ -1452,41 +5425,24 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/gaxios": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.1.tgz",
- "integrity": "sha512-Odju3uBUJyVCkW64nLD4wKLhbh93bh6vIg/ZIXkWiLPBrdgtc65+tls/qml+un3pr6JqYVFDZbbmLDQT68rTOQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "extend": "^3.0.2",
- "https-proxy-agent": "^7.0.1",
- "node-fetch": "^3.3.2"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/gcp-metadata": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-7.0.1.tgz",
- "integrity": "sha512-UcO3kefx6dCcZkgcTGgVOTFb7b1LlQ02hY1omMjjrrBzkajRMCFgYOjs7J71WqnuG1k2b+9ppGL7FsOfhZMQKQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "gaxios": "^7.0.0",
- "google-logging-utils": "^1.0.0",
- "json-bigint": "^1.0.0"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/generic-pool": {
- "version": "3.9.0",
- "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz",
- "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==",
+ "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": ">= 4"
+ "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==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
}
},
"node_modules/get-intrinsic": {
@@ -1513,6 +5469,16 @@
"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",
@@ -1526,36 +5492,35 @@
"node": ">= 0.4"
}
},
- "node_modules/get-tsconfig": {
- "version": "4.10.1",
- "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz",
- "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==",
+ "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",
- "dependencies": {
- "resolve-pkg-maps": "^1.0.0"
+ "engines": {
+ "node": ">=10"
},
"funding": {
- "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"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",
+ "version": "10.4.5",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
+ "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
"dev": true,
"license": "ISC",
"dependencies": {
- "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"
+ "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"
},
- "engines": {
- "node": "*"
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
@@ -1574,52 +5539,64 @@
"node": ">= 6"
}
},
- "node_modules/google-auth-library": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.1.0.tgz",
- "integrity": "sha512-GspVjZj1RbyRWpQ9FbAXMKjFGzZwDKnUHi66JJ+tcjcu5/xYAP1pdlWotCuIkMwjfVsxxDvsGZXGLzRt72D0sQ==",
- "license": "Apache-2.0",
+ "node_modules/glob-to-regexp": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
+ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
+ "dev": true,
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/glob/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "dev": true,
+ "license": "ISC",
"dependencies": {
- "base64-js": "^1.3.0",
- "ecdsa-sig-formatter": "^1.0.11",
- "gaxios": "^7.0.0",
- "gcp-metadata": "^7.0.0",
- "google-logging-utils": "^1.0.0",
- "gtoken": "^8.0.0",
- "jws": "^4.0.0"
+ "brace-expansion": "^2.0.1"
},
"engines": {
- "node": ">=18"
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/google-auth-library/node_modules/jwa": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz",
- "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==",
+ "node_modules/globals": {
+ "version": "13.24.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
+ "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "buffer-equal-constant-time": "^1.0.1",
- "ecdsa-sig-formatter": "1.0.11",
- "safe-buffer": "^5.0.1"
- }
- },
- "node_modules/google-auth-library/node_modules/jws": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz",
- "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==",
- "license": "MIT",
- "dependencies": {
- "jwa": "^2.0.0",
- "safe-buffer": "^5.0.1"
- }
- },
- "node_modules/google-logging-utils": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.1.tgz",
- "integrity": "sha512-rcX58I7nqpu4mbKztFeOAObbomBbHU2oIb/d3tJfF3dizGSApqtSwYJigGCooHdnMyQBIw8BrWyK96w3YXgr6A==",
- "license": "Apache-2.0",
+ "type-fest": "^0.20.2"
+ },
"engines": {
- "node": ">=14"
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/gopd": {
@@ -1634,38 +5611,82 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/gtoken": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-8.0.0.tgz",
- "integrity": "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw==",
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/graphemer": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/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": {
- "gaxios": "^7.0.0",
- "jws": "^4.0.0"
+ "minimist": "^1.2.5",
+ "neo-async": "^2.6.2",
+ "source-map": "^0.6.1",
+ "wordwrap": "^1.0.0"
+ },
+ "bin": {
+ "handlebars": "bin/handlebars"
},
"engines": {
- "node": ">=18"
+ "node": ">=0.4.7"
+ },
+ "optionalDependencies": {
+ "uglify-js": "^3.1.4"
}
},
- "node_modules/gtoken/node_modules/jwa": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz",
- "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==",
- "license": "MIT",
- "dependencies": {
- "buffer-equal-constant-time": "^1.0.1",
- "ecdsa-sig-formatter": "1.0.11",
- "safe-buffer": "^5.0.1"
+ "node_modules/handlebars/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/gtoken/node_modules/jws": {
+ "node_modules/has-flag": {
"version": "4.0.0",
- "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz",
- "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/has-own-prop": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-own-prop/-/has-own-prop-2.0.0.tgz",
+ "integrity": "sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "jwa": "^2.0.0",
- "safe-buffer": "^5.0.1"
+ "es-define-property": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-symbols": {
@@ -1680,6 +5701,21 @@
"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",
@@ -1692,58 +5728,43 @@
"node": ">= 0.4"
}
},
+ "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==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
+ "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
"license": "MIT",
"dependencies": {
- "depd": "2.0.0",
- "inherits": "2.0.4",
- "setprototypeof": "1.2.0",
- "statuses": "2.0.1",
- "toidentifier": "1.0.1"
+ "depd": "~2.0.0",
+ "inherits": "~2.0.4",
+ "setprototypeof": "~1.2.0",
+ "statuses": "~2.0.2",
+ "toidentifier": "~1.0.1"
},
"engines": {
"node": ">= 0.8"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
}
},
- "node_modules/https-proxy-agent": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
- "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
- "license": "MIT",
- "dependencies": {
- "agent-base": "^7.1.2",
- "debug": "4"
- },
+ "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": ">= 14"
+ "node": ">=10.17.0"
}
},
- "node_modules/https-proxy-agent/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/https-proxy-agent/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/iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
@@ -1756,6 +5777,83 @@
"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": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/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",
@@ -1774,6 +5872,57 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"license": "ISC"
},
+ "node_modules/inquirer": {
+ "version": "8.2.6",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz",
+ "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.1.1",
+ "cli-cursor": "^3.1.0",
+ "cli-width": "^3.0.0",
+ "external-editor": "^3.0.3",
+ "figures": "^3.0.0",
+ "lodash": "^4.17.21",
+ "mute-stream": "0.0.8",
+ "ora": "^5.4.1",
+ "run-async": "^2.4.0",
+ "rxjs": "^7.5.5",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0",
+ "through": "^2.3.6",
+ "wrap-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/ioredis": {
+ "version": "5.9.2",
+ "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.9.2.tgz",
+ "integrity": "sha512-tAAg/72/VxOUW7RQSX1pIxJVucYKcjFjfvj60L57jrZpYCHC3XN0WCQ3sNYL4Gmvv+7GPvTAjc+KSdeNuE8oWQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@ioredis/commands": "1.5.0",
+ "cluster-key-slot": "^1.1.0",
+ "debug": "^4.3.4",
+ "denque": "^2.1.0",
+ "lodash.defaults": "^4.2.0",
+ "lodash.isarguments": "^3.1.0",
+ "redis-errors": "^1.2.0",
+ "redis-parser": "^3.0.0",
+ "standard-as-callback": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=12.22.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/ioredis"
+ }
+ },
"node_modules/ipaddr.js": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
@@ -1783,6 +5932,13 @@
"node": ">= 0.10"
}
},
+ "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/is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
@@ -1822,6 +5978,26 @@
"node": ">=0.10.0"
}
},
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-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-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
@@ -1835,6 +6011,16 @@
"node": ">=0.10.0"
}
},
+ "node_modules/is-interactive": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
+ "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
@@ -1845,13 +6031,966 @@
"node": ">=0.12.0"
}
},
- "node_modules/json-bigint": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz",
- "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==",
+ "node_modules/is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/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-source-maps": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz",
+ "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "debug": "^4.1.1",
+ "istanbul-lib-coverage": "^3.0.0",
+ "source-map": "^0.6.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-source-maps/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/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/iterare": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/iterare/-/iterare-1.2.1.tgz",
+ "integrity": "sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/jackspeak": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
+ "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "node_modules/jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz",
+ "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@jest/core": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "import-local": "^3.0.2",
+ "jest-cli": "^29.7.0"
+ },
+ "bin": {
+ "jest": "bin/jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.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": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz",
+ "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "bignumber.js": "^9.0.0"
+ "execa": "^5.0.0",
+ "jest-util": "^29.7.0",
+ "p-limit": "^3.1.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-circus": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz",
+ "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/expect": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "co": "^4.6.0",
+ "dedent": "^1.0.0",
+ "is-generator-fn": "^2.0.0",
+ "jest-each": "^29.7.0",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "p-limit": "^3.1.0",
+ "pretty-format": "^29.7.0",
+ "pure-rand": "^6.0.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-cli": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz",
+ "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/core": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "create-jest": "^29.7.0",
+ "exit": "^0.1.2",
+ "import-local": "^3.0.2",
+ "jest-config": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "yargs": "^17.3.1"
+ },
+ "bin": {
+ "jest": "bin/jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-config": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz",
+ "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@jest/test-sequencer": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "babel-jest": "^29.7.0",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "deepmerge": "^4.2.2",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "jest-circus": "^29.7.0",
+ "jest-environment-node": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-runner": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "parse-json": "^5.2.0",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@types/node": "*",
+ "ts-node": ">=9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "ts-node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-config/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/jest-config/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/jest-config/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/jest-diff": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz",
+ "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "diff-sequences": "^29.6.3",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-docblock": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz",
+ "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "detect-newline": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-each": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz",
+ "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-environment-node": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz",
+ "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-get-type": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz",
+ "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-haste-map": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz",
+ "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/graceful-fs": "^4.1.3",
+ "@types/node": "*",
+ "anymatch": "^3.0.3",
+ "fb-watchman": "^2.0.0",
+ "graceful-fs": "^4.2.9",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "walker": "^1.0.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "^2.3.2"
+ }
+ },
+ "node_modules/jest-leak-detector": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz",
+ "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-matcher-utils": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz",
+ "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "jest-diff": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-message-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz",
+ "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.12.13",
+ "@jest/types": "^29.6.3",
+ "@types/stack-utils": "^2.0.0",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-mock": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz",
+ "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.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": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz",
+ "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-resolve": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz",
+ "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-pnp-resolver": "^1.2.2",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "resolve": "^1.20.0",
+ "resolve.exports": "^2.0.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-resolve-dependencies": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz",
+ "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jest-regex-util": "^29.6.3",
+ "jest-snapshot": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-runner": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz",
+ "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/console": "^29.7.0",
+ "@jest/environment": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "emittery": "^0.13.1",
+ "graceful-fs": "^4.2.9",
+ "jest-docblock": "^29.7.0",
+ "jest-environment-node": "^29.7.0",
+ "jest-haste-map": "^29.7.0",
+ "jest-leak-detector": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-resolve": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-watcher": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "p-limit": "^3.1.0",
+ "source-map-support": "0.5.13"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-runner/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/jest-runner/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/jest-runtime": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz",
+ "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/globals": "^29.7.0",
+ "@jest/source-map": "^29.6.3",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "cjs-module-lexer": "^1.0.0",
+ "collect-v8-coverage": "^1.0.0",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-mock": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-bom": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-runtime/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/jest-runtime/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/jest-runtime/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/jest-snapshot": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz",
+ "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@babel/generator": "^7.7.2",
+ "@babel/plugin-syntax-jsx": "^7.7.2",
+ "@babel/plugin-syntax-typescript": "^7.7.2",
+ "@babel/types": "^7.3.3",
+ "@jest/expect-utils": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "babel-preset-current-node-syntax": "^1.0.0",
+ "chalk": "^4.0.0",
+ "expect": "^29.7.0",
+ "graceful-fs": "^4.2.9",
+ "jest-diff": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "natural-compare": "^1.4.0",
+ "pretty-format": "^29.7.0",
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-util/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/jest-validate": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz",
+ "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "camelcase": "^6.2.0",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.6.3",
+ "leven": "^3.1.0",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.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": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz",
+ "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "emittery": "^0.13.1",
+ "jest-util": "^29.7.0",
+ "string-length": "^4.0.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-worker": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz",
+ "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "jest-util": "^29.7.0",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "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/jose": {
+ "version": "4.15.9",
+ "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.9.tgz",
+ "integrity": "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/panva"
+ }
+ },
+ "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.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
+ "dev": true,
+ "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-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-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/json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/jsonc-parser": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz",
+ "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/jsonfile": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz",
+ "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "universalify": "^2.0.0"
+ },
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
}
},
"node_modules/jsonwebtoken": {
@@ -1876,12 +7015,6 @@
"npm": ">=6"
}
},
- "node_modules/jsonwebtoken/node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "license": "MIT"
- },
"node_modules/jwa": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz",
@@ -1893,22 +7026,154 @@
"safe-buffer": "^5.0.1"
}
},
- "node_modules/jws": {
+ "node_modules/jwks-rsa": {
"version": "3.2.2",
- "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
- "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
+ "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-3.2.2.tgz",
+ "integrity": "sha512-BqTyEDV+lS8F2trk3A+qJnxV5Q9EqKCBJOPti3W97r7qTympCZjb7h2X6f2kc+0K3rsSTY1/6YG2eaXKoj497w==",
"license": "MIT",
"dependencies": {
- "jwa": "^1.4.1",
+ "@types/jsonwebtoken": "^9.0.4",
+ "debug": "^4.3.4",
+ "jose": "^4.15.4",
+ "limiter": "^1.1.5",
+ "lru-memoizer": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/jws": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.3.tgz",
+ "integrity": "sha512-byiJ0FLRdLdSVSReO/U4E7RoEyOCKnEnEPMjq3HxWtvzLsV08/i5RQKsFVNkCldrCaPr2vDNAOMsfs8T/Hze7g==",
+ "license": "MIT",
+ "dependencies": {
+ "jwa": "^1.4.2",
"safe-buffer": "^5.0.1"
}
},
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/kleur": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
+ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "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/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/libphonenumber-js": {
+ "version": "1.12.35",
+ "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.35.tgz",
+ "integrity": "sha512-T/Cz6iLcsZdb5jDncDcUNhSAJ0VlSC9TnsqtBNdpkaAmy24/R1RhErtNWVWBrcUZKs9hSgaVsBkc7HxYnazIfw==",
+ "license": "MIT"
+ },
+ "node_modules/limiter": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz",
+ "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA=="
+ },
+ "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/loader-runner": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz",
+ "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.11.5"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.clonedeep": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
+ "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.defaults": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
+ "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==",
+ "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.isarguments": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
+ "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==",
+ "license": "MIT"
+ },
"node_modules/lodash.isboolean": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
@@ -1939,12 +7204,110 @@
"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.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/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/log-symbols": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+ "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/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/lru-memoizer": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-2.3.0.tgz",
+ "integrity": "sha512-GXn7gyHAMhO13WSKrIiNfztwxodVsP8IoZ3XfrJV4yH2x0/OeTO/FIaAHTY5YekdGgW94njfuKmyyt1E0mR6Ug==",
+ "license": "MIT",
+ "dependencies": {
+ "lodash.clonedeep": "^4.5.0",
+ "lru-cache": "6.0.0"
+ }
+ },
+ "node_modules/lru-memoizer/node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/lru-memoizer/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "license": "ISC"
+ },
+ "node_modules/magic-string": {
+ "version": "0.30.8",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz",
+ "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.4.15"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "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",
@@ -1952,6 +7315,16 @@
"dev": 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",
@@ -1970,6 +7343,19 @@
"node": ">= 0.6"
}
},
+ "node_modules/memfs": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz",
+ "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==",
+ "dev": true,
+ "license": "Unlicense",
+ "dependencies": {
+ "fs-monkey": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
"node_modules/merge-descriptors": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
@@ -1979,6 +7365,23 @@
"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/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
"node_modules/methods": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
@@ -1988,6 +7391,33 @@
"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/micromatch/node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
"node_modules/mime": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
@@ -2021,46 +7451,99 @@
"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": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+ "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
"dev": true,
"license": "ISC",
"dependencies": {
- "brace-expansion": "^1.1.7"
+ "brace-expansion": "^2.0.1"
},
"engines": {
- "node": "*"
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/minimist": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
- "dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/mkdirp": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
- "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "node_modules/minipass": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
"dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/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"
- },
- "engines": {
- "node": ">=10"
}
},
"node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "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/mute-stream": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
+ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "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": {
@@ -2072,44 +7555,64 @@
"node": ">= 0.6"
}
},
- "node_modules/node-domexception": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
- "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
- "deprecated": "Use your platform's native DOMException instead",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/jimmywarting"
- },
- {
- "type": "github",
- "url": "https://paypal.me/jimmywarting"
- }
- ],
+ "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-abort-controller": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz",
+ "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/node-emoji": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz",
+ "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==",
+ "dev": true,
"license": "MIT",
- "engines": {
- "node": ">=10.5.0"
+ "dependencies": {
+ "lodash": "^4.17.21"
}
},
"node_modules/node-fetch": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
- "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
"license": "MIT",
"dependencies": {
- "data-uri-to-buffer": "^4.0.0",
- "fetch-blob": "^3.1.4",
- "formdata-polyfill": "^4.0.10"
+ "whatwg-url": "^5.0.0"
},
"engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ "node": "4.x || >=6.0.0"
},
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/node-fetch"
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
}
},
+ "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.27",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz",
+ "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@@ -2120,6 +7623,19 @@
"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",
@@ -2163,6 +7679,155 @@
"wrappy": "1"
}
},
+ "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/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/ora": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz",
+ "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "bl": "^4.1.0",
+ "chalk": "^4.1.0",
+ "cli-cursor": "^3.1.0",
+ "cli-spinners": "^2.5.0",
+ "is-interactive": "^1.0.0",
+ "is-unicode-supported": "^0.1.0",
+ "log-symbols": "^4.1.0",
+ "strip-ansi": "^6.0.0",
+ "wcwidth": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/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==",
+ "dev": true,
+ "license": "BlueOak-1.0.0"
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/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",
@@ -2172,6 +7837,53 @@
"node": ">= 0.8"
}
},
+ "node_modules/passport": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz",
+ "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "passport-strategy": "1.x.x",
+ "pause": "0.0.1",
+ "utils-merge": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/jaredhanson"
+ }
+ },
+ "node_modules/passport-jwt": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.1.tgz",
+ "integrity": "sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==",
+ "license": "MIT",
+ "dependencies": {
+ "jsonwebtoken": "^9.0.0",
+ "passport-strategy": "^1.0.0"
+ }
+ },
+ "node_modules/passport-strategy": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz",
+ "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==",
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "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",
@@ -2182,6 +7894,16 @@
"node": ">=0.10.0"
}
},
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/path-parse": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
@@ -2189,151 +7911,261 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/path-scurry/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "dev": true,
+ "license": "ISC"
+ },
"node_modules/path-to-regexp": {
- "version": "0.1.12",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
- "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==",
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz",
+ "integrity": "sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==",
"license": "MIT"
},
- "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/picomatch": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "node_modules/path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=8.6"
+ "node": ">=8"
+ }
+ },
+ "node_modules/pause": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz",
+ "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg=="
+ },
+ "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": "4.0.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.1.tgz",
+ "integrity": "sha512-xUXwsxNjwTQ8K3GnT4pCJm+xq3RUPQbmkYJTP5aFIfNIvbcc/4MUxgBaaRSZJ6yGJZiGSyYlM6MzwTsRk8SYCg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
- "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==",
+ "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/pkg-dir/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/pkg-dir/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/pkg-dir/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/pkg-dir/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/pluralize": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz",
+ "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==",
+ "dev": true,
"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==",
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
"license": "MIT",
"engines": {
- "node": ">=0.10.0"
+ "node": ">= 0.8.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==",
+ "node_modules/prettier": {
+ "version": "3.8.1",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz",
+ "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==",
+ "dev": true,
"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"
+ "peer": true,
+ "bin": {
+ "prettier": "bin/prettier.cjs"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/prettier-linter-helpers": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz",
+ "integrity": "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-diff": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.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/prisma": {
+ "version": "5.22.0",
+ "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.22.0.tgz",
+ "integrity": "sha512-vtpjW3XuYCSnMsNVBjLMNkTj6OZbudcPPTPYHqX0CJfpcdWciI1dM8uHETwmDxxiqEwCIE6WvXucWUetJgfu/A==",
+ "devOptional": true,
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "peer": true,
+ "dependencies": {
+ "@prisma/engines": "5.22.0"
+ },
+ "bin": {
+ "prisma": "build/index.js"
+ },
+ "engines": {
+ "node": ">=16.13"
+ },
+ "optionalDependencies": {
+ "fsevents": "2.3.3"
+ }
+ },
+ "node_modules/prompts": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
+ "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "kleur": "^3.0.3",
+ "sisteransi": "^1.0.5"
+ },
+ "engines": {
+ "node": ">= 6"
}
},
"node_modules/proxy-addr": {
@@ -2349,13 +8181,46 @@
"node": ">= 0.10"
}
},
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+ "license": "MIT"
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pure-rand": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz",
+ "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==",
+ "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.13.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
- "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
+ "version": "6.14.1",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz",
+ "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==",
"license": "BSD-3-Clause",
"dependencies": {
- "side-channel": "^1.0.6"
+ "side-channel": "^1.1.0"
},
"engines": {
"node": ">=0.6"
@@ -2364,6 +8229,37 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/randombytes": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
"node_modules/range-parser": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
@@ -2374,20 +8270,41 @@
}
},
"node_modules/raw-body": {
- "version": "2.5.2",
- "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
- "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
+ "version": "2.5.3",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz",
+ "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==",
"license": "MIT",
"dependencies": {
- "bytes": "3.1.2",
- "http-errors": "2.0.0",
- "iconv-lite": "0.4.24",
- "unpipe": "1.0.0"
+ "bytes": "~3.1.2",
+ "http-errors": "~2.0.1",
+ "iconv-lite": "~0.4.24",
+ "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",
@@ -2401,31 +8318,85 @@
"node": ">=8.10.0"
}
},
- "node_modules/redis": {
- "version": "4.7.1",
- "resolved": "https://registry.npmjs.org/redis/-/redis-4.7.1.tgz",
- "integrity": "sha512-S1bJDnqLftzHXHP8JsT5II/CtHWQrASX5K96REjWjlmWKrviSOLWmM7QnRLstAWsu1VBBV1ffV6DzCvxNP0UJQ==",
+ "node_modules/readdirp/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/redis-errors": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
+ "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/redis-parser": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz",
+ "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==",
"license": "MIT",
- "workspaces": [
- "./packages/*"
- ],
"dependencies": {
- "@redis/bloom": "1.2.0",
- "@redis/client": "1.6.1",
- "@redis/graph": "1.1.1",
- "@redis/json": "1.0.7",
- "@redis/search": "1.2.0",
- "@redis/time-series": "1.1.0"
+ "redis-errors": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/reflect-metadata": {
+ "version": "0.1.14",
+ "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.14.tgz",
+ "integrity": "sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==",
+ "license": "Apache-2.0",
+ "peer": true
+ },
+ "node_modules/repeat-string": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+ "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
}
},
"node_modules/resolve": {
- "version": "1.22.10",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
- "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
+ "version": "1.22.11",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz",
+ "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "is-core-module": "^2.16.0",
+ "is-core-module": "^2.16.1",
"path-parse": "^1.0.7",
"supports-preserve-symlinks-flag": "^1.0.0"
},
@@ -2439,20 +8410,85 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/resolve-pkg-maps": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
- "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
+ "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",
- "funding": {
- "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
+ "dependencies": {
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/resolve-cwd/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/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/resolve.exports": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz",
+ "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/restore-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+ "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/restore-cursor/node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/reusify": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
+ "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
}
},
"node_modules/rimraf": {
- "version": "2.7.1",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
- "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"deprecated": "Rimraf versions prior to v4 are no longer supported",
"dev": true,
"license": "ISC",
@@ -2461,6 +8497,99 @@
},
"bin": {
"rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/rimraf/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/rimraf/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/rimraf/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/run-async": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
+ "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/rxjs": {
+ "version": "7.8.2",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
+ "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "dependencies": {
+ "tslib": "^2.1.0"
}
},
"node_modules/safe-buffer": {
@@ -2489,10 +8618,64 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"license": "MIT"
},
+ "node_modules/schema-utils": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
+ "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/json-schema": "^7.0.8",
+ "ajv": "^6.12.5",
+ "ajv-keywords": "^3.5.2"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
+ },
+ "node_modules/schema-utils/node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/schema-utils/node_modules/ajv-keywords": {
+ "version": "3.5.2",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
+ "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "ajv": "^6.9.1"
+ }
+ },
+ "node_modules/schema-utils/node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/semver": {
- "version": "7.7.2",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
- "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
+ "version": "7.7.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
+ "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
@@ -2502,65 +8685,116 @@
}
},
"node_modules/send": {
- "version": "0.19.0",
- "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
- "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
+ "version": "0.19.2",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz",
+ "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==",
"license": "MIT",
"dependencies": {
"debug": "2.6.9",
"depd": "2.0.0",
"destroy": "1.2.0",
- "encodeurl": "~1.0.2",
+ "encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
- "fresh": "0.5.2",
- "http-errors": "2.0.0",
+ "fresh": "~0.5.2",
+ "http-errors": "~2.0.1",
"mime": "1.6.0",
"ms": "2.1.3",
- "on-finished": "2.4.1",
+ "on-finished": "~2.4.1",
"range-parser": "~1.2.1",
- "statuses": "2.0.1"
+ "statuses": "~2.0.2"
},
"engines": {
"node": ">= 0.8.0"
}
},
- "node_modules/send/node_modules/encodeurl": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
- "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+ "node_modules/send/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"license": "MIT",
- "engines": {
- "node": ">= 0.8"
+ "dependencies": {
+ "ms": "2.0.0"
}
},
- "node_modules/send/node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "node_modules/send/node_modules/debug/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"license": "MIT"
},
+ "node_modules/serialize-javascript": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
+ "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "randombytes": "^2.1.0"
+ }
+ },
"node_modules/serve-static": {
- "version": "1.16.2",
- "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
- "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
+ "version": "1.16.3",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz",
+ "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==",
"license": "MIT",
"dependencies": {
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"parseurl": "~1.3.3",
- "send": "0.19.0"
+ "send": "~0.19.1"
},
"engines": {
"node": ">= 0.8.0"
}
},
+ "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==",
+ "dev": true,
+ "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/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/side-channel": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
@@ -2633,14 +8867,44 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/sisteransi": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
+ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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/source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "version": "0.7.4",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
+ "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
- "node": ">=0.10.0"
+ "node": ">= 8"
}
},
"node_modules/source-map-support": {
@@ -2654,42 +8918,260 @@
"source-map": "^0.6.0"
}
},
- "node_modules/split2": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
- "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
- "license": "ISC",
+ "node_modules/source-map-support/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": ">= 10.x"
+ "node": ">=0.10.0"
}
},
+ "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/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/stack-utils/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/standard-as-callback": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz",
+ "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==",
+ "license": "MIT"
+ },
"node_modules/statuses": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
- "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+ "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/streamsearch": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
+ "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "node_modules/string-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-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs": {
+ "name": "string-width",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi-cjs": {
+ "name": "strip-ansi",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/strip-bom": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
- "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+ "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": ">=4"
+ "node": ">=8"
+ }
+ },
+ "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": "2.0.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
- "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
+ "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": ">=0.10.0"
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/strtok3": {
+ "version": "10.3.4",
+ "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.3.4.tgz",
+ "integrity": "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==",
+ "license": "MIT",
+ "dependencies": {
+ "@tokenizer/token": "^0.3.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Borewit"
+ }
+ },
+ "node_modules/superagent": {
+ "version": "8.1.2",
+ "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.1.2.tgz",
+ "integrity": "sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA==",
+ "deprecated": "Please upgrade to superagent v10.2.2+, see release notes at https://github.com/forwardemail/superagent/releases/tag/v10.2.2 - maintenance is supported by Forward Email @ https://forwardemail.net",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "component-emitter": "^1.3.0",
+ "cookiejar": "^2.1.4",
+ "debug": "^4.3.4",
+ "fast-safe-stringify": "^2.1.1",
+ "form-data": "^4.0.0",
+ "formidable": "^2.1.2",
+ "methods": "^1.1.2",
+ "mime": "2.6.0",
+ "qs": "^6.11.0",
+ "semver": "^7.3.8"
+ },
+ "engines": {
+ "node": ">=6.4.0 <13 || >=14"
+ }
+ },
+ "node_modules/superagent/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/supertest": {
+ "version": "6.3.4",
+ "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.3.4.tgz",
+ "integrity": "sha512-erY3HFDG0dPnhw4U+udPfrzXa4xhSG+n4rxfRuZWCUvjFWwKl+OxWf/7zk50s84/fAAs7vf5QAb9uRa0cCykxw==",
+ "deprecated": "Please upgrade to supertest v7.1.3+, see release notes at https://github.com/forwardemail/supertest/releases/tag/v7.1.3 - maintenance is supported by Forward Email @ https://forwardemail.net",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "methods": "^1.1.2",
+ "superagent": "^8.1.2"
+ },
+ "engines": {
+ "node": ">=6.4.0"
+ }
+ },
+ "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==",
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
}
},
"node_modules/supports-preserve-symlinks-flag": {
@@ -2705,6 +9187,253 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/symbol-observable": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz",
+ "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/synckit": {
+ "version": "0.11.12",
+ "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.12.tgz",
+ "integrity": "sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==",
+ "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/tapable": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz",
+ "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
+ },
+ "node_modules/terser": {
+ "version": "5.46.0",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz",
+ "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "@jridgewell/source-map": "^0.3.3",
+ "acorn": "^8.15.0",
+ "commander": "^2.20.0",
+ "source-map-support": "~0.5.20"
+ },
+ "bin": {
+ "terser": "bin/terser"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/terser-webpack-plugin": {
+ "version": "5.3.16",
+ "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz",
+ "integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.25",
+ "jest-worker": "^27.4.5",
+ "schema-utils": "^4.3.0",
+ "serialize-javascript": "^6.0.2",
+ "terser": "^5.31.1"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "^5.1.0"
+ },
+ "peerDependenciesMeta": {
+ "@swc/core": {
+ "optional": true
+ },
+ "esbuild": {
+ "optional": true
+ },
+ "uglify-js": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/terser-webpack-plugin/node_modules/jest-worker": {
+ "version": "27.5.1",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
+ "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ }
+ },
+ "node_modules/terser-webpack-plugin/node_modules/schema-utils": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz",
+ "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/json-schema": "^7.0.9",
+ "ajv": "^8.9.0",
+ "ajv-formats": "^2.1.1",
+ "ajv-keywords": "^5.1.0"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
+ },
+ "node_modules/terser-webpack-plugin/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/terser/node_modules/commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/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-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/tmp": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "os-tmpdir": "~1.0.2"
+ },
+ "engines": {
+ "node": ">=0.6.0"
+ }
+ },
+ "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-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -2727,6 +9456,30 @@
"node": ">=0.6"
}
},
+ "node_modules/token-types": {
+ "version": "6.1.2",
+ "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.1.2.tgz",
+ "integrity": "sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==",
+ "license": "MIT",
+ "dependencies": {
+ "@borewit/text-codec": "^0.2.1",
+ "@tokenizer/token": "^0.3.0",
+ "ieee754": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Borewit"
+ }
+ },
+ "node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+ "license": "MIT"
+ },
"node_modules/tree-kill": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
@@ -2737,12 +9490,113 @@
"tree-kill": "cli.js"
}
},
+ "node_modules/ts-api-utils": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz",
+ "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=16"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.2.0"
+ }
+ },
+ "node_modules/ts-jest": {
+ "version": "29.4.6",
+ "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.6.tgz",
+ "integrity": "sha512-fSpWtOO/1AjSNQguk43hb/JCo16oJDnMJf3CdEGNkqsEX3t0KX96xvyX1D7PfLCpVoKu4MfVrqUkFyblYoY4lA==",
+ "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.3",
+ "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-loader": {
+ "version": "9.5.4",
+ "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.4.tgz",
+ "integrity": "sha512-nCz0rEwunlTZiy6rXFByQU1kVVpCIgUpc/psFiKVrUwrizdnIbRFu8w7bxhUF0X613DYwT4XzrZHpVyMe758hQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "enhanced-resolve": "^5.0.0",
+ "micromatch": "^4.0.0",
+ "semver": "^7.3.4",
+ "source-map": "^0.7.4"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "typescript": "*",
+ "webpack": "^5.0.0"
+ }
+ },
"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==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@cspotcode/source-map-support": "^0.8.0",
"@tsconfig/node10": "^1.0.7",
@@ -2781,72 +9635,87 @@
}
}
},
- "node_modules/ts-node-dev": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-2.0.0.tgz",
- "integrity": "sha512-ywMrhCfH6M75yftYvrvNarLEY+SUXtUvU8/0Z6llrHQVBx12GiFk5sStF8UdfE/yfzk9IAq7O5EEbTQsxlBI8w==",
+ "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==",
"dev": true,
"license": "MIT",
"dependencies": {
- "chokidar": "^3.5.1",
- "dynamic-dedupe": "^0.3.0",
+ "json5": "^2.2.2",
"minimist": "^1.2.6",
- "mkdirp": "^1.0.4",
- "resolve": "^1.0.0",
- "rimraf": "^2.6.1",
- "source-map-support": "^0.5.12",
- "tree-kill": "^1.2.2",
- "ts-node": "^10.4.0",
- "tsconfig": "^7.0.0"
- },
- "bin": {
- "ts-node-dev": "lib/bin.js",
- "tsnd": "lib/bin.js"
+ "strip-bom": "^3.0.0"
},
"engines": {
- "node": ">=0.8.0"
- },
- "peerDependencies": {
- "node-notifier": "*",
- "typescript": "*"
- },
- "peerDependenciesMeta": {
- "node-notifier": {
- "optional": true
- }
+ "node": ">=6"
}
},
- "node_modules/tsconfig": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz",
- "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==",
+ "node_modules/tsconfig-paths-webpack-plugin": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.2.0.tgz",
+ "integrity": "sha512-zbem3rfRS8BgeNK50Zz5SIQgXzLafiHjOwUAvk/38/o1jHn/V5QAgVUcz884or7WYcPaH3N2CIfUc2u0ul7UcA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@types/strip-bom": "^3.0.0",
- "@types/strip-json-comments": "0.0.30",
- "strip-bom": "^3.0.0",
- "strip-json-comments": "^2.0.0"
+ "chalk": "^4.1.0",
+ "enhanced-resolve": "^5.7.0",
+ "tapable": "^2.2.1",
+ "tsconfig-paths": "^4.1.2"
+ },
+ "engines": {
+ "node": ">=10.13.0"
}
},
- "node_modules/tsx": {
- "version": "4.20.3",
- "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.3.tgz",
- "integrity": "sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ==",
+ "node_modules/tsconfig-paths/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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "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-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
"dev": true,
"license": "MIT",
"dependencies": {
- "esbuild": "~0.25.0",
- "get-tsconfig": "^4.7.5"
- },
- "bin": {
- "tsx": "dist/cli.mjs"
+ "prelude-ls": "^1.2.1"
},
"engines": {
- "node": ">=18.0.0"
+ "node": ">= 0.8.0"
+ }
+ },
+ "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.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true,
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=10"
},
- "optionalDependencies": {
- "fsevents": "~2.3.3"
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/type-is": {
@@ -2862,12 +9731,19 @@
"node": ">= 0.6"
}
},
+ "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/typescript": {
- "version": "5.8.3",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
- "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
+ "version": "5.9.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
+ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"dev": true,
"license": "Apache-2.0",
+ "peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -2876,13 +9752,60 @@
"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/uid": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/uid/-/uid-2.0.2.tgz",
+ "integrity": "sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==",
+ "license": "MIT",
+ "dependencies": {
+ "@lukeed/csprng": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/uint8array-extras": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.5.0.tgz",
+ "integrity": "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/undici-types": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
- "dev": true,
"license": "MIT"
},
+ "node_modules/universalify": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
+ "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
"node_modules/unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
@@ -2892,6 +9815,53 @@
"node": ">= 0.8"
}
},
+ "node_modules/update-browserslist-db": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
+ "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "license": "MIT"
+ },
"node_modules/utils-merge": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
@@ -2901,19 +9871,6 @@
"node": ">= 0.4.0"
}
},
- "node_modules/uuid": {
- "version": "9.0.1",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
- "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
- "funding": [
- "https://github.com/sponsors/broofa",
- "https://github.com/sponsors/ctavan"
- ],
- "license": "MIT",
- "bin": {
- "uuid": "dist/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",
@@ -2921,6 +9878,30 @@
"dev": 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/validator": {
+ "version": "13.15.26",
+ "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.26.tgz",
+ "integrity": "sha512-spH26xU080ydGggxRyR1Yhcbgx+j3y5jbNXk/8L+iRvdIEQ4uTRH2Sgf2dokud6Q4oAtsbNvJ1Ft+9xmm6IZcA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
"node_modules/vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
@@ -2930,15 +9911,237 @@
"node": ">= 0.8"
}
},
- "node_modules/web-streams-polyfill": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
- "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
+ "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/watchpack": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz",
+ "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "glob-to-regexp": "^0.4.1",
+ "graceful-fs": "^4.1.2"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/wcwidth": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
+ "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "defaults": "^1.0.3"
+ }
+ },
+ "node_modules/webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/webpack": {
+ "version": "5.104.1",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.104.1.tgz",
+ "integrity": "sha512-Qphch25abbMNtekmEGJmeRUhLDbe+QfiWTiqpKYkpCOWY64v9eyl+KRRLmqOFA2AvKPpc9DC6+u2n76tQLBoaA==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/eslint-scope": "^3.7.7",
+ "@types/estree": "^1.0.8",
+ "@types/json-schema": "^7.0.15",
+ "@webassemblyjs/ast": "^1.14.1",
+ "@webassemblyjs/wasm-edit": "^1.14.1",
+ "@webassemblyjs/wasm-parser": "^1.14.1",
+ "acorn": "^8.15.0",
+ "acorn-import-phases": "^1.0.3",
+ "browserslist": "^4.28.1",
+ "chrome-trace-event": "^1.0.2",
+ "enhanced-resolve": "^5.17.4",
+ "es-module-lexer": "^2.0.0",
+ "eslint-scope": "5.1.1",
+ "events": "^3.2.0",
+ "glob-to-regexp": "^0.4.1",
+ "graceful-fs": "^4.2.11",
+ "json-parse-even-better-errors": "^2.3.1",
+ "loader-runner": "^4.3.1",
+ "mime-types": "^2.1.27",
+ "neo-async": "^2.6.2",
+ "schema-utils": "^4.3.3",
+ "tapable": "^2.3.0",
+ "terser-webpack-plugin": "^5.3.16",
+ "watchpack": "^2.4.4",
+ "webpack-sources": "^3.3.3"
+ },
+ "bin": {
+ "webpack": "bin/webpack.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependenciesMeta": {
+ "webpack-cli": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/webpack-node-externals": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/webpack-node-externals/-/webpack-node-externals-3.0.0.tgz",
+ "integrity": "sha512-LnL6Z3GGDPht/AigwRh2dvL9PQPFQ8skEpVrWZXLWBYmqcaojHNN0onvHzie6rq7EWKrrBfPYqNEzTJgiwEQDQ==",
+ "dev": true,
"license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/webpack-sources": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz",
+ "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/webpack/node_modules/eslint-scope": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/webpack/node_modules/estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/webpack/node_modules/schema-utils": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz",
+ "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/json-schema": "^7.0.9",
+ "ajv": "^8.9.0",
+ "ajv-formats": "^2.1.1",
+ "ajv-keywords": "^5.1.0"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
+ },
+ "node_modules/whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "license": "MIT",
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
"engines": {
"node": ">= 8"
}
},
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/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": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi-cjs": {
+ "name": "wrap-ansi",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
@@ -2946,6 +10149,27 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/write-file-atomic": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz",
+ "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^3.0.7"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/write-file-atomic/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/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
@@ -2955,12 +10179,52 @@
"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==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/yallist": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "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/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/yn": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
@@ -2971,13 +10235,17 @@
"node": ">=6"
}
},
- "node_modules/zod": {
- "version": "3.25.76",
- "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
- "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
+ "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/colinhacks"
+ "url": "https://github.com/sponsors/sindresorhus"
}
}
}
diff --git a/backend/package.json b/backend/package.json
index 9b970bd..31f4dfe 100644
--- a/backend/package.json
+++ b/backend/package.json
@@ -1,41 +1,93 @@
{
"name": "vip-coordinator-backend",
"version": "1.0.0",
- "description": "Backend API for VIP Coordinator Dashboard",
- "main": "dist/index.js",
- "scripts": {
- "start": "node dist/index.js",
- "dev": "npx tsx src/index.ts",
- "build": "tsc",
- "test": "echo \"Error: no test specified\" && exit 1"
- },
- "keywords": [
- "vip",
- "coordinator",
- "dashboard",
- "api"
- ],
+ "description": "VIP Coordinator Backend API - NestJS + Prisma + Auth0",
"author": "",
- "license": "ISC",
+ "private": true,
+ "license": "MIT",
+ "scripts": {
+ "build": "nest build",
+ "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
+ "start": "nest start",
+ "start:dev": "nest start --watch",
+ "start:debug": "nest start --debug --watch",
+ "start:prod": "node dist/main",
+ "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
+ "test": "jest",
+ "test:watch": "jest --watch",
+ "test:cov": "jest --coverage",
+ "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
+ "test:e2e": "jest --config ./test/jest-e2e.json",
+ "prisma:generate": "prisma generate",
+ "prisma:migrate": "prisma migrate dev",
+ "prisma:studio": "prisma studio",
+ "prisma:seed": "ts-node prisma/seed.ts"
+ },
"dependencies": {
- "cors": "^2.8.5",
- "dotenv": "^16.3.1",
- "express": "^4.18.2",
- "jsonwebtoken": "^9.0.2",
- "pg": "^8.11.3",
- "redis": "^4.6.8",
- "uuid": "^9.0.0"
+ "@casl/ability": "^6.8.0",
+ "@casl/prisma": "^1.6.1",
+ "@nestjs/axios": "^4.0.1",
+ "@nestjs/common": "^10.3.0",
+ "@nestjs/config": "^3.1.1",
+ "@nestjs/core": "^10.3.0",
+ "@nestjs/jwt": "^10.2.0",
+ "@nestjs/mapped-types": "^2.1.0",
+ "@nestjs/passport": "^10.0.3",
+ "@nestjs/platform-express": "^10.3.0",
+ "@prisma/client": "^5.8.1",
+ "axios": "^1.6.5",
+ "class-transformer": "^0.5.1",
+ "class-validator": "^0.14.0",
+ "ioredis": "^5.3.2",
+ "jwks-rsa": "^3.1.0",
+ "passport": "^0.7.0",
+ "passport-jwt": "^4.0.1",
+ "reflect-metadata": "^0.1.14",
+ "rxjs": "^7.8.1"
},
"devDependencies": {
- "@types/cors": "^2.8.13",
- "@types/express": "^4.17.17",
- "@types/jsonwebtoken": "^9.0.2",
- "@types/node": "^20.5.0",
- "@types/pg": "^8.10.2",
- "@types/uuid": "^9.0.2",
- "ts-node": "^10.9.1",
- "ts-node-dev": "^2.0.0",
- "tsx": "^4.7.0",
- "typescript": "^5.6.0"
+ "@nestjs/cli": "^10.2.1",
+ "@nestjs/schematics": "^10.0.3",
+ "@nestjs/testing": "^10.3.0",
+ "@types/express": "^4.17.21",
+ "@types/jest": "^29.5.11",
+ "@types/node": "^20.10.6",
+ "@types/passport-jwt": "^4.0.0",
+ "@types/supertest": "^6.0.2",
+ "@typescript-eslint/eslint-plugin": "^6.17.0",
+ "@typescript-eslint/parser": "^6.17.0",
+ "eslint": "^8.56.0",
+ "eslint-config-prettier": "^9.1.0",
+ "eslint-plugin-prettier": "^5.1.2",
+ "jest": "^29.7.0",
+ "prettier": "^3.1.1",
+ "prisma": "^5.8.1",
+ "source-map-support": "^0.5.21",
+ "supertest": "^6.3.3",
+ "ts-jest": "^29.1.1",
+ "ts-loader": "^9.5.1",
+ "ts-node": "^10.9.2",
+ "tsconfig-paths": "^4.2.0",
+ "typescript": "^5.3.3"
+ },
+ "jest": {
+ "moduleFileExtensions": [
+ "js",
+ "json",
+ "ts"
+ ],
+ "rootDir": "src",
+ "testRegex": ".*\\.spec\\.ts$",
+ "transform": {
+ "^.+\\.(t|j)s$": "ts-jest"
+ },
+ "collectCoverageFrom": [
+ "**/*.(t|j)s"
+ ],
+ "coverageDirectory": "../coverage",
+ "testEnvironment": "node"
+ },
+ "prisma": {
+ "seed": "ts-node prisma/seed.ts"
}
}
diff --git a/backend/prisma/migrations/20260125085806_init/migration.sql b/backend/prisma/migrations/20260125085806_init/migration.sql
new file mode 100644
index 0000000..27a327e
--- /dev/null
+++ b/backend/prisma/migrations/20260125085806_init/migration.sql
@@ -0,0 +1,137 @@
+-- CreateEnum
+CREATE TYPE "Role" AS ENUM ('ADMINISTRATOR', 'COORDINATOR', 'DRIVER');
+
+-- CreateEnum
+CREATE TYPE "Department" AS ENUM ('OFFICE_OF_DEVELOPMENT', 'ADMIN');
+
+-- CreateEnum
+CREATE TYPE "ArrivalMode" AS ENUM ('FLIGHT', 'SELF_DRIVING');
+
+-- CreateEnum
+CREATE TYPE "EventType" AS ENUM ('TRANSPORT', 'MEETING', 'EVENT', 'MEAL', 'ACCOMMODATION');
+
+-- CreateEnum
+CREATE TYPE "EventStatus" AS ENUM ('SCHEDULED', 'IN_PROGRESS', 'COMPLETED', 'CANCELLED');
+
+-- CreateTable
+CREATE TABLE "users" (
+ "id" TEXT NOT NULL,
+ "auth0Id" TEXT NOT NULL,
+ "email" TEXT NOT NULL,
+ "name" TEXT,
+ "picture" TEXT,
+ "role" "Role" NOT NULL DEFAULT 'COORDINATOR',
+ "isApproved" BOOLEAN NOT NULL DEFAULT false,
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updatedAt" TIMESTAMP(3) NOT NULL,
+ "deletedAt" TIMESTAMP(3),
+
+ CONSTRAINT "users_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "vips" (
+ "id" TEXT NOT NULL,
+ "name" TEXT NOT NULL,
+ "organization" TEXT,
+ "department" "Department" NOT NULL,
+ "arrivalMode" "ArrivalMode" NOT NULL,
+ "expectedArrival" TIMESTAMP(3),
+ "airportPickup" BOOLEAN NOT NULL DEFAULT false,
+ "venueTransport" BOOLEAN NOT NULL DEFAULT false,
+ "notes" TEXT,
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updatedAt" TIMESTAMP(3) NOT NULL,
+ "deletedAt" TIMESTAMP(3),
+
+ CONSTRAINT "vips_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "flights" (
+ "id" TEXT NOT NULL,
+ "vipId" TEXT NOT NULL,
+ "flightNumber" TEXT NOT NULL,
+ "flightDate" TIMESTAMP(3) NOT NULL,
+ "segment" INTEGER NOT NULL DEFAULT 1,
+ "departureAirport" TEXT NOT NULL,
+ "arrivalAirport" TEXT NOT NULL,
+ "scheduledDeparture" TIMESTAMP(3),
+ "scheduledArrival" TIMESTAMP(3),
+ "actualDeparture" TIMESTAMP(3),
+ "actualArrival" TIMESTAMP(3),
+ "status" TEXT,
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updatedAt" TIMESTAMP(3) NOT NULL,
+
+ CONSTRAINT "flights_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "drivers" (
+ "id" TEXT NOT NULL,
+ "name" TEXT NOT NULL,
+ "phone" TEXT NOT NULL,
+ "department" "Department",
+ "userId" TEXT,
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updatedAt" TIMESTAMP(3) NOT NULL,
+ "deletedAt" TIMESTAMP(3),
+
+ CONSTRAINT "drivers_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "schedule_events" (
+ "id" TEXT NOT NULL,
+ "vipId" TEXT NOT NULL,
+ "title" TEXT NOT NULL,
+ "location" TEXT,
+ "startTime" TIMESTAMP(3) NOT NULL,
+ "endTime" TIMESTAMP(3) NOT NULL,
+ "description" TEXT,
+ "type" "EventType" NOT NULL DEFAULT 'TRANSPORT',
+ "status" "EventStatus" NOT NULL DEFAULT 'SCHEDULED',
+ "driverId" TEXT,
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updatedAt" TIMESTAMP(3) NOT NULL,
+ "deletedAt" TIMESTAMP(3),
+
+ CONSTRAINT "schedule_events_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateIndex
+CREATE UNIQUE INDEX "users_auth0Id_key" ON "users"("auth0Id");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "users_email_key" ON "users"("email");
+
+-- CreateIndex
+CREATE INDEX "flights_vipId_idx" ON "flights"("vipId");
+
+-- CreateIndex
+CREATE INDEX "flights_flightNumber_flightDate_idx" ON "flights"("flightNumber", "flightDate");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "drivers_userId_key" ON "drivers"("userId");
+
+-- CreateIndex
+CREATE INDEX "schedule_events_vipId_idx" ON "schedule_events"("vipId");
+
+-- CreateIndex
+CREATE INDEX "schedule_events_driverId_idx" ON "schedule_events"("driverId");
+
+-- CreateIndex
+CREATE INDEX "schedule_events_startTime_endTime_idx" ON "schedule_events"("startTime", "endTime");
+
+-- AddForeignKey
+ALTER TABLE "flights" ADD CONSTRAINT "flights_vipId_fkey" FOREIGN KEY ("vipId") REFERENCES "vips"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "drivers" ADD CONSTRAINT "drivers_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "schedule_events" ADD CONSTRAINT "schedule_events_vipId_fkey" FOREIGN KEY ("vipId") REFERENCES "vips"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "schedule_events" ADD CONSTRAINT "schedule_events_driverId_fkey" FOREIGN KEY ("driverId") REFERENCES "drivers"("id") ON DELETE SET NULL ON UPDATE CASCADE;
diff --git a/backend/prisma/migrations/20260125124048_add_vehicle_management/migration.sql b/backend/prisma/migrations/20260125124048_add_vehicle_management/migration.sql
new file mode 100644
index 0000000..b8713c9
--- /dev/null
+++ b/backend/prisma/migrations/20260125124048_add_vehicle_management/migration.sql
@@ -0,0 +1,50 @@
+-- CreateEnum
+CREATE TYPE "VehicleType" AS ENUM ('VAN', 'SUV', 'SEDAN', 'BUS', 'GOLF_CART', 'TRUCK');
+
+-- CreateEnum
+CREATE TYPE "VehicleStatus" AS ENUM ('AVAILABLE', 'IN_USE', 'MAINTENANCE', 'RESERVED');
+
+-- AlterTable
+ALTER TABLE "drivers" ADD COLUMN "isAvailable" BOOLEAN NOT NULL DEFAULT true,
+ADD COLUMN "shiftEndTime" TIMESTAMP(3),
+ADD COLUMN "shiftStartTime" TIMESTAMP(3);
+
+-- AlterTable
+ALTER TABLE "schedule_events" ADD COLUMN "actualEndTime" TIMESTAMP(3),
+ADD COLUMN "actualStartTime" TIMESTAMP(3),
+ADD COLUMN "dropoffLocation" TEXT,
+ADD COLUMN "notes" TEXT,
+ADD COLUMN "pickupLocation" TEXT,
+ADD COLUMN "vehicleId" TEXT;
+
+-- CreateTable
+CREATE TABLE "vehicles" (
+ "id" TEXT NOT NULL,
+ "name" TEXT NOT NULL,
+ "type" "VehicleType" NOT NULL DEFAULT 'VAN',
+ "licensePlate" TEXT,
+ "seatCapacity" INTEGER NOT NULL,
+ "status" "VehicleStatus" NOT NULL DEFAULT 'AVAILABLE',
+ "currentDriverId" TEXT,
+ "notes" TEXT,
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updatedAt" TIMESTAMP(3) NOT NULL,
+ "deletedAt" TIMESTAMP(3),
+
+ CONSTRAINT "vehicles_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateIndex
+CREATE UNIQUE INDEX "vehicles_currentDriverId_key" ON "vehicles"("currentDriverId");
+
+-- CreateIndex
+CREATE INDEX "schedule_events_vehicleId_idx" ON "schedule_events"("vehicleId");
+
+-- CreateIndex
+CREATE INDEX "schedule_events_status_idx" ON "schedule_events"("status");
+
+-- AddForeignKey
+ALTER TABLE "vehicles" ADD CONSTRAINT "vehicles_currentDriverId_fkey" FOREIGN KEY ("currentDriverId") REFERENCES "drivers"("id") ON DELETE SET NULL ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "schedule_events" ADD CONSTRAINT "schedule_events_vehicleId_fkey" FOREIGN KEY ("vehicleId") REFERENCES "vehicles"("id") ON DELETE SET NULL ON UPDATE CASCADE;
diff --git a/backend/prisma/migrations/migration_lock.toml b/backend/prisma/migrations/migration_lock.toml
new file mode 100644
index 0000000..fbffa92
--- /dev/null
+++ b/backend/prisma/migrations/migration_lock.toml
@@ -0,0 +1,3 @@
+# Please do not edit this file manually
+# It should be added in your version-control system (i.e. Git)
+provider = "postgresql"
\ No newline at end of file
diff --git a/backend/prisma/schema.prisma b/backend/prisma/schema.prisma
new file mode 100644
index 0000000..78e8213
--- /dev/null
+++ b/backend/prisma/schema.prisma
@@ -0,0 +1,227 @@
+// VIP Coordinator - Prisma Schema
+// This is your database schema (source of truth)
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+}
+
+// ============================================
+// User Management
+// ============================================
+
+model User {
+ id String @id @default(uuid())
+ auth0Id String @unique // Auth0 sub claim
+ email String @unique
+ name String?
+ picture String?
+ role Role @default(COORDINATOR)
+ isApproved Boolean @default(false)
+ driver Driver? // Optional linked driver account
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ deletedAt DateTime? // Soft delete
+
+ @@map("users")
+}
+
+enum Role {
+ ADMINISTRATOR
+ COORDINATOR
+ DRIVER
+}
+
+// ============================================
+// VIP Management
+// ============================================
+
+model VIP {
+ id String @id @default(uuid())
+ name String
+ organization String?
+ department Department
+ arrivalMode ArrivalMode
+ expectedArrival DateTime? // For self-driving arrivals
+ airportPickup Boolean @default(false)
+ venueTransport Boolean @default(false)
+ notes String? @db.Text
+ flights Flight[]
+ events ScheduleEvent[]
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ deletedAt DateTime? // Soft delete
+
+ @@map("vips")
+}
+
+enum Department {
+ OFFICE_OF_DEVELOPMENT
+ ADMIN
+}
+
+enum ArrivalMode {
+ FLIGHT
+ SELF_DRIVING
+}
+
+// ============================================
+// Flight Tracking
+// ============================================
+
+model Flight {
+ id String @id @default(uuid())
+ vipId String
+ vip VIP @relation(fields: [vipId], references: [id], onDelete: Cascade)
+ flightNumber String
+ flightDate DateTime
+ segment Int @default(1) // For multi-segment itineraries
+ departureAirport String // IATA code (e.g., "JFK")
+ arrivalAirport String // IATA code (e.g., "LAX")
+ scheduledDeparture DateTime?
+ scheduledArrival DateTime?
+ actualDeparture DateTime?
+ actualArrival DateTime?
+ status String? // scheduled, delayed, landed, etc.
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+
+ @@map("flights")
+ @@index([vipId])
+ @@index([flightNumber, flightDate])
+}
+
+// ============================================
+// Driver Management
+// ============================================
+
+model Driver {
+ id String @id @default(uuid())
+ name String
+ phone String
+ department Department?
+ userId String? @unique
+ user User? @relation(fields: [userId], references: [id])
+
+ // Shift/Availability
+ shiftStartTime DateTime? // When driver's shift starts
+ shiftEndTime DateTime? // When driver's shift ends
+ isAvailable Boolean @default(true)
+
+ events ScheduleEvent[]
+ assignedVehicle Vehicle? @relation("AssignedDriver")
+
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ deletedAt DateTime? // Soft delete
+
+ @@map("drivers")
+}
+
+// ============================================
+// Vehicle Management
+// ============================================
+
+model Vehicle {
+ id String @id @default(uuid())
+ name String // "Blue Van", "Suburban #3"
+ type VehicleType @default(VAN)
+ licensePlate String?
+ seatCapacity Int // Total seats (e.g., 8)
+ status VehicleStatus @default(AVAILABLE)
+
+ // Current assignment
+ currentDriverId String? @unique
+ currentDriver Driver? @relation("AssignedDriver", fields: [currentDriverId], references: [id])
+
+ // Relationships
+ events ScheduleEvent[]
+
+ notes String? @db.Text
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ deletedAt DateTime? // Soft delete
+
+ @@map("vehicles")
+}
+
+enum VehicleType {
+ VAN // 7-15 seats
+ SUV // 5-8 seats
+ SEDAN // 4-5 seats
+ BUS // 15+ seats
+ GOLF_CART // 2-6 seats
+ TRUCK // For equipment/supplies
+}
+
+enum VehicleStatus {
+ AVAILABLE // Ready to use
+ IN_USE // Currently on a trip
+ MAINTENANCE // Out of service
+ RESERVED // Scheduled for upcoming trip
+}
+
+// ============================================
+// Schedule & Event Management
+// ============================================
+
+model ScheduleEvent {
+ id String @id @default(uuid())
+ vipId String
+ vip VIP @relation(fields: [vipId], references: [id], onDelete: Cascade)
+ title String
+
+ // Location details
+ pickupLocation String?
+ dropoffLocation String?
+ location String? // For non-transport events
+
+ // Timing
+ startTime DateTime
+ endTime DateTime
+ actualStartTime DateTime?
+ actualEndTime DateTime?
+
+ description String? @db.Text
+ type EventType @default(TRANSPORT)
+ status EventStatus @default(SCHEDULED)
+
+ // Assignments
+ driverId String?
+ driver Driver? @relation(fields: [driverId], references: [id], onDelete: SetNull)
+ vehicleId String?
+ vehicle Vehicle? @relation(fields: [vehicleId], references: [id], onDelete: SetNull)
+
+ // Metadata
+ notes String? @db.Text
+
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ deletedAt DateTime? // Soft delete
+
+ @@map("schedule_events")
+ @@index([vipId])
+ @@index([driverId])
+ @@index([vehicleId])
+ @@index([startTime, endTime])
+ @@index([status])
+}
+
+enum EventType {
+ TRANSPORT
+ MEETING
+ EVENT
+ MEAL
+ ACCOMMODATION
+}
+
+enum EventStatus {
+ SCHEDULED
+ IN_PROGRESS
+ COMPLETED
+ CANCELLED
+}
diff --git a/backend/prisma/seed.ts b/backend/prisma/seed.ts
new file mode 100644
index 0000000..7b155c9
--- /dev/null
+++ b/backend/prisma/seed.ts
@@ -0,0 +1,165 @@
+import { PrismaClient, Role, Department, ArrivalMode, EventType, EventStatus } from '@prisma/client';
+
+const prisma = new PrismaClient();
+
+async function main() {
+ console.log('🌱 Seeding database...');
+
+ // Clean up existing data (careful in production!)
+ await prisma.scheduleEvent.deleteMany({});
+ await prisma.flight.deleteMany({});
+ await prisma.driver.deleteMany({});
+ await prisma.vIP.deleteMany({});
+ await prisma.user.deleteMany({});
+
+ console.log('✅ Cleared existing data');
+
+ // Create sample users
+ const admin = await prisma.user.create({
+ data: {
+ auth0Id: 'auth0|admin-sample-id',
+ email: 'admin@example.com',
+ name: 'Admin User',
+ role: Role.ADMINISTRATOR,
+ isApproved: true,
+ },
+ });
+
+ const coordinator = await prisma.user.create({
+ data: {
+ auth0Id: 'auth0|coordinator-sample-id',
+ email: 'coordinator@example.com',
+ name: 'Coordinator User',
+ role: Role.COORDINATOR,
+ isApproved: true,
+ },
+ });
+
+ console.log('✅ Created sample users');
+
+ // Create sample drivers
+ const driver1 = await prisma.driver.create({
+ data: {
+ name: 'John Smith',
+ phone: '+1 (555) 123-4567',
+ department: Department.OFFICE_OF_DEVELOPMENT,
+ },
+ });
+
+ const driver2 = await prisma.driver.create({
+ data: {
+ name: 'Jane Doe',
+ phone: '+1 (555) 987-6543',
+ department: Department.ADMIN,
+ },
+ });
+
+ console.log('✅ Created sample drivers');
+
+ // Create sample VIPs
+ const vip1 = await prisma.vIP.create({
+ data: {
+ name: 'Dr. Robert Johnson',
+ organization: 'Tech Corporation',
+ department: Department.OFFICE_OF_DEVELOPMENT,
+ arrivalMode: ArrivalMode.FLIGHT,
+ airportPickup: true,
+ venueTransport: true,
+ notes: 'Prefers window seat, dietary restriction: vegetarian',
+ flights: {
+ create: [
+ {
+ flightNumber: 'AA123',
+ flightDate: new Date('2026-02-15'),
+ segment: 1,
+ departureAirport: 'JFK',
+ arrivalAirport: 'LAX',
+ scheduledDeparture: new Date('2026-02-15T08:00:00'),
+ scheduledArrival: new Date('2026-02-15T11:30:00'),
+ status: 'scheduled',
+ },
+ ],
+ },
+ },
+ });
+
+ const vip2 = await prisma.vIP.create({
+ data: {
+ name: 'Ms. Sarah Williams',
+ organization: 'Global Foundation',
+ department: Department.ADMIN,
+ arrivalMode: ArrivalMode.SELF_DRIVING,
+ expectedArrival: new Date('2026-02-16T14:00:00'),
+ airportPickup: false,
+ venueTransport: true,
+ notes: 'Bringing assistant',
+ },
+ });
+
+ console.log('✅ Created sample VIPs');
+
+ // Create sample events
+ await prisma.scheduleEvent.create({
+ data: {
+ vipId: vip1.id,
+ title: 'Airport Pickup',
+ location: 'LAX Terminal 4',
+ startTime: new Date('2026-02-15T11:30:00'),
+ endTime: new Date('2026-02-15T12:30:00'),
+ description: 'Pick up Dr. Johnson from LAX',
+ type: EventType.TRANSPORT,
+ status: EventStatus.SCHEDULED,
+ driverId: driver1.id,
+ },
+ });
+
+ await prisma.scheduleEvent.create({
+ data: {
+ vipId: vip1.id,
+ title: 'Welcome Dinner',
+ location: 'Grand Hotel Restaurant',
+ startTime: new Date('2026-02-15T19:00:00'),
+ endTime: new Date('2026-02-15T21:00:00'),
+ description: 'Welcome dinner with board members',
+ type: EventType.MEAL,
+ status: EventStatus.SCHEDULED,
+ driverId: driver2.id,
+ },
+ });
+
+ await prisma.scheduleEvent.create({
+ data: {
+ vipId: vip2.id,
+ title: 'Conference Transport',
+ location: 'Convention Center',
+ startTime: new Date('2026-02-16T14:30:00'),
+ endTime: new Date('2026-02-16T15:00:00'),
+ description: 'Transport to conference venue',
+ type: EventType.TRANSPORT,
+ status: EventStatus.SCHEDULED,
+ driverId: driver1.id,
+ },
+ });
+
+ console.log('✅ Created sample events');
+
+ console.log('\n🎉 Database seeded successfully!');
+ console.log('\nSample Users:');
+ console.log('- Admin: admin@example.com');
+ console.log('- Coordinator: coordinator@example.com');
+ console.log('\nSample VIPs:');
+ console.log('- Dr. Robert Johnson (Flight arrival)');
+ console.log('- Ms. Sarah Williams (Self-driving)');
+ console.log('\nSample Drivers:');
+ console.log('- John Smith');
+ console.log('- Jane Doe');
+}
+
+main()
+ .catch((e) => {
+ console.error('❌ Error seeding database:', e);
+ process.exit(1);
+ })
+ .finally(async () => {
+ await prisma.$disconnect();
+ });
diff --git a/backend/src/app.controller.ts b/backend/src/app.controller.ts
new file mode 100644
index 0000000..8800336
--- /dev/null
+++ b/backend/src/app.controller.ts
@@ -0,0 +1,14 @@
+import { Controller, Get } from '@nestjs/common';
+import { AppService } from './app.service';
+import { Public } from './auth/decorators/public.decorator';
+
+@Controller()
+export class AppController {
+ constructor(private readonly appService: AppService) {}
+
+ @Get('health')
+ @Public() // Health check should be public
+ getHealth() {
+ return this.appService.getHealth();
+ }
+}
diff --git a/backend/src/app.module.ts b/backend/src/app.module.ts
new file mode 100644
index 0000000..2f25b8b
--- /dev/null
+++ b/backend/src/app.module.ts
@@ -0,0 +1,46 @@
+import { Module } from '@nestjs/common';
+import { ConfigModule } from '@nestjs/config';
+import { APP_GUARD } from '@nestjs/core';
+import { AppController } from './app.controller';
+import { AppService } from './app.service';
+import { PrismaModule } from './prisma/prisma.module';
+import { AuthModule } from './auth/auth.module';
+import { UsersModule } from './users/users.module';
+import { VipsModule } from './vips/vips.module';
+import { DriversModule } from './drivers/drivers.module';
+import { VehiclesModule } from './vehicles/vehicles.module';
+import { EventsModule } from './events/events.module';
+import { FlightsModule } from './flights/flights.module';
+import { JwtAuthGuard } from './auth/guards/jwt-auth.guard';
+
+@Module({
+ imports: [
+ // Load environment variables
+ ConfigModule.forRoot({
+ isGlobal: true,
+ envFilePath: '.env',
+ }),
+
+ // Core modules
+ PrismaModule,
+ AuthModule,
+
+ // Feature modules
+ UsersModule,
+ VipsModule,
+ DriversModule,
+ VehiclesModule,
+ EventsModule,
+ FlightsModule,
+ ],
+ controllers: [AppController],
+ providers: [
+ AppService,
+ // Apply JWT auth guard globally (unless @Public() is used)
+ {
+ provide: APP_GUARD,
+ useClass: JwtAuthGuard,
+ },
+ ],
+})
+export class AppModule {}
diff --git a/backend/src/app.service.ts b/backend/src/app.service.ts
new file mode 100644
index 0000000..e3cd850
--- /dev/null
+++ b/backend/src/app.service.ts
@@ -0,0 +1,14 @@
+import { Injectable } from '@nestjs/common';
+
+@Injectable()
+export class AppService {
+ getHealth() {
+ return {
+ status: 'ok',
+ timestamp: new Date().toISOString(),
+ service: 'VIP Coordinator API',
+ version: '1.0.0',
+ environment: process.env.NODE_ENV || 'development',
+ };
+ }
+}
diff --git a/backend/src/auth/abilities/ability.factory.ts b/backend/src/auth/abilities/ability.factory.ts
new file mode 100644
index 0000000..a005049
--- /dev/null
+++ b/backend/src/auth/abilities/ability.factory.ts
@@ -0,0 +1,90 @@
+import { AbilityBuilder, PureAbility, AbilityClass, ExtractSubjectType, InferSubjects } from '@casl/ability';
+import { Injectable } from '@nestjs/common';
+import { Role, User, VIP, Driver, ScheduleEvent, Flight, Vehicle } from '@prisma/client';
+
+/**
+ * Define all possible actions in the system
+ */
+export enum Action {
+ Manage = 'manage', // Special: allows everything
+ Create = 'create',
+ Read = 'read',
+ Update = 'update',
+ Delete = 'delete',
+ Approve = 'approve', // Special: for user approval
+ UpdateStatus = 'update-status', // Special: for drivers to update event status
+}
+
+/**
+ * Define all subjects (resources) in the system
+ */
+export type Subjects =
+ | InferSubjects
+ | 'User'
+ | 'VIP'
+ | 'Driver'
+ | 'ScheduleEvent'
+ | 'Flight'
+ | 'Vehicle'
+ | 'all';
+
+/**
+ * Define the AppAbility type
+ */
+export type AppAbility = PureAbility<[Action, Subjects]>;
+
+@Injectable()
+export class AbilityFactory {
+ /**
+ * Define abilities for a user based on their role
+ */
+ defineAbilitiesFor(user: User): AppAbility {
+ const { can, cannot, build } = new AbilityBuilder(
+ PureAbility as AbilityClass,
+ );
+
+ // Define permissions based on role
+ if (user.role === Role.ADMINISTRATOR) {
+ // Administrators can do everything
+ can(Action.Manage, 'all');
+ } else if (user.role === Role.COORDINATOR) {
+ // Coordinators have full access except user management
+ can(Action.Read, 'all');
+ can(Action.Create, ['VIP', 'Driver', 'ScheduleEvent', 'Flight', 'Vehicle']);
+ can(Action.Update, ['VIP', 'Driver', 'ScheduleEvent', 'Flight', 'Vehicle']);
+ can(Action.Delete, ['VIP', 'Driver', 'ScheduleEvent', 'Flight', 'Vehicle']);
+
+ // Cannot manage users
+ cannot(Action.Create, 'User');
+ cannot(Action.Update, 'User');
+ cannot(Action.Delete, 'User');
+ cannot(Action.Approve, 'User');
+ } else if (user.role === Role.DRIVER) {
+ // Drivers can only read most resources
+ can(Action.Read, ['VIP', 'Driver', 'ScheduleEvent', 'Vehicle']);
+
+ // Drivers can update status of their own events
+ can(Action.UpdateStatus, 'ScheduleEvent', { driverId: user.driver?.id });
+
+ // Cannot access flights
+ cannot(Action.Read, 'Flight');
+
+ // Cannot access users
+ cannot(Action.Read, 'User');
+ }
+
+ return build({
+ // Detect subject type from object
+ detectSubjectType: (item) =>
+ item.constructor as ExtractSubjectType,
+ });
+ }
+
+ /**
+ * Check if user can perform action on subject
+ */
+ canUserPerform(user: User, action: Action, subject: Subjects): boolean {
+ const ability = this.defineAbilitiesFor(user);
+ return ability.can(action, subject);
+ }
+}
diff --git a/backend/src/auth/auth.controller.ts b/backend/src/auth/auth.controller.ts
new file mode 100644
index 0000000..e25ba66
--- /dev/null
+++ b/backend/src/auth/auth.controller.ts
@@ -0,0 +1,17 @@
+import { Controller, Get, UseGuards } from '@nestjs/common';
+import { AuthService } from './auth.service';
+import { JwtAuthGuard } from './guards/jwt-auth.guard';
+import { CurrentUser } from './decorators/current-user.decorator';
+import { User } from '@prisma/client';
+
+@Controller('auth')
+export class AuthController {
+ constructor(private authService: AuthService) {}
+
+ @Get('profile')
+ @UseGuards(JwtAuthGuard)
+ async getProfile(@CurrentUser() user: User) {
+ // Return user profile (password already excluded by Prisma)
+ return user;
+ }
+}
diff --git a/backend/src/auth/auth.module.ts b/backend/src/auth/auth.module.ts
new file mode 100644
index 0000000..7139111
--- /dev/null
+++ b/backend/src/auth/auth.module.ts
@@ -0,0 +1,30 @@
+import { Module } from '@nestjs/common';
+import { PassportModule } from '@nestjs/passport';
+import { JwtModule } from '@nestjs/jwt';
+import { HttpModule } from '@nestjs/axios';
+import { ConfigModule, ConfigService } from '@nestjs/config';
+import { AuthService } from './auth.service';
+import { AuthController } from './auth.controller';
+import { JwtStrategy } from './strategies/jwt.strategy';
+import { AbilityFactory } from './abilities/ability.factory';
+
+@Module({
+ imports: [
+ HttpModule,
+ PassportModule.register({ defaultStrategy: 'jwt' }),
+ JwtModule.registerAsync({
+ imports: [ConfigModule],
+ useFactory: async (configService: ConfigService) => ({
+ secret: configService.get('JWT_SECRET') || 'development-secret-key',
+ signOptions: {
+ expiresIn: '7d',
+ },
+ }),
+ inject: [ConfigService],
+ }),
+ ],
+ controllers: [AuthController],
+ providers: [AuthService, JwtStrategy, AbilityFactory],
+ exports: [AuthService, PassportModule, JwtModule, AbilityFactory],
+})
+export class AuthModule {}
diff --git a/backend/src/auth/auth.service.ts b/backend/src/auth/auth.service.ts
new file mode 100644
index 0000000..9cd4dc5
--- /dev/null
+++ b/backend/src/auth/auth.service.ts
@@ -0,0 +1,66 @@
+import { Injectable, Logger } from '@nestjs/common';
+import { PrismaService } from '../prisma/prisma.service';
+import { Role } from '@prisma/client';
+
+@Injectable()
+export class AuthService {
+ private readonly logger = new Logger(AuthService.name);
+
+ constructor(private prisma: PrismaService) {}
+
+ /**
+ * Validate and get/create user from Auth0 token payload
+ */
+ async validateUser(payload: any) {
+ const namespace = 'https://vip-coordinator-api';
+ const auth0Id = payload.sub;
+ const email = payload[`${namespace}/email`] || payload.email || `${auth0Id}@auth0.local`;
+ const name = payload[`${namespace}/name`] || payload.name || 'Unknown User';
+ const picture = payload[`${namespace}/picture`] || payload.picture;
+
+ // Check if user exists
+ let user = await this.prisma.user.findUnique({
+ where: { auth0Id },
+ include: { driver: true },
+ });
+
+ if (!user) {
+ // Check if this is the first user (auto-approve as admin)
+ const userCount = await this.prisma.user.count();
+ const isFirstUser = userCount === 0;
+
+ this.logger.log(
+ `Creating new user: ${email} (isFirstUser: ${isFirstUser})`,
+ );
+
+ // Create new user
+ user = await this.prisma.user.create({
+ data: {
+ auth0Id,
+ email,
+ name,
+ picture,
+ role: isFirstUser ? Role.ADMINISTRATOR : Role.DRIVER,
+ isApproved: isFirstUser, // Auto-approve first user
+ },
+ include: { driver: true },
+ });
+
+ this.logger.log(
+ `User created: ${user.email} with role ${user.role} (approved: ${user.isApproved})`,
+ );
+ }
+
+ return user;
+ }
+
+ /**
+ * Get current user profile
+ */
+ async getCurrentUser(auth0Id: string) {
+ return this.prisma.user.findUnique({
+ where: { auth0Id },
+ include: { driver: true },
+ });
+ }
+}
diff --git a/backend/src/auth/decorators/check-ability.decorator.ts b/backend/src/auth/decorators/check-ability.decorator.ts
new file mode 100644
index 0000000..9da1608
--- /dev/null
+++ b/backend/src/auth/decorators/check-ability.decorator.ts
@@ -0,0 +1,39 @@
+import { SetMetadata } from '@nestjs/common';
+import { Action, Subjects } from '../abilities/ability.factory';
+import { CHECK_ABILITY, RequiredPermission } from '../guards/abilities.guard';
+
+/**
+ * Decorator to check CASL abilities on a route
+ *
+ * @example
+ * @CheckAbilities({ action: Action.Create, subject: 'VIP' })
+ * async create(@Body() dto: CreateVIPDto) {
+ * return this.service.create(dto);
+ * }
+ *
+ * @example Multiple permissions (all must be satisfied)
+ * @CheckAbilities(
+ * { action: Action.Read, subject: 'VIP' },
+ * { action: Action.Update, subject: 'VIP' }
+ * )
+ */
+export const CheckAbilities = (...permissions: RequiredPermission[]) =>
+ SetMetadata(CHECK_ABILITY, permissions);
+
+/**
+ * Helper functions for common permission checks
+ */
+export const CanCreate = (subject: Subjects) =>
+ CheckAbilities({ action: Action.Create, subject });
+
+export const CanRead = (subject: Subjects) =>
+ CheckAbilities({ action: Action.Read, subject });
+
+export const CanUpdate = (subject: Subjects) =>
+ CheckAbilities({ action: Action.Update, subject });
+
+export const CanDelete = (subject: Subjects) =>
+ CheckAbilities({ action: Action.Delete, subject });
+
+export const CanManage = (subject: Subjects) =>
+ CheckAbilities({ action: Action.Manage, subject });
diff --git a/backend/src/auth/decorators/current-user.decorator.ts b/backend/src/auth/decorators/current-user.decorator.ts
new file mode 100644
index 0000000..7919497
--- /dev/null
+++ b/backend/src/auth/decorators/current-user.decorator.ts
@@ -0,0 +1,8 @@
+import { createParamDecorator, ExecutionContext } from '@nestjs/common';
+
+export const CurrentUser = createParamDecorator(
+ (data: unknown, ctx: ExecutionContext) => {
+ const request = ctx.switchToHttp().getRequest();
+ return request.user;
+ },
+);
diff --git a/backend/src/auth/decorators/public.decorator.ts b/backend/src/auth/decorators/public.decorator.ts
new file mode 100644
index 0000000..b3845e1
--- /dev/null
+++ b/backend/src/auth/decorators/public.decorator.ts
@@ -0,0 +1,4 @@
+import { SetMetadata } from '@nestjs/common';
+
+export const IS_PUBLIC_KEY = 'isPublic';
+export const Public = () => SetMetadata(IS_PUBLIC_KEY, true);
diff --git a/backend/src/auth/decorators/roles.decorator.ts b/backend/src/auth/decorators/roles.decorator.ts
new file mode 100644
index 0000000..0d0c0d7
--- /dev/null
+++ b/backend/src/auth/decorators/roles.decorator.ts
@@ -0,0 +1,5 @@
+import { SetMetadata } from '@nestjs/common';
+import { Role } from '@prisma/client';
+
+export const ROLES_KEY = 'roles';
+export const Roles = (...roles: Role[]) => SetMetadata(ROLES_KEY, roles);
diff --git a/backend/src/auth/guards/abilities.guard.ts b/backend/src/auth/guards/abilities.guard.ts
new file mode 100644
index 0000000..1403a20
--- /dev/null
+++ b/backend/src/auth/guards/abilities.guard.ts
@@ -0,0 +1,64 @@
+import { Injectable, CanActivate, ExecutionContext, ForbiddenException } from '@nestjs/common';
+import { Reflector } from '@nestjs/core';
+import { AbilityFactory, Action, Subjects } from '../abilities/ability.factory';
+
+/**
+ * Interface for required permissions
+ */
+export interface RequiredPermission {
+ action: Action;
+ subject: Subjects;
+}
+
+/**
+ * Metadata key for permissions
+ */
+export const CHECK_ABILITY = 'check_ability';
+
+/**
+ * Guard that checks CASL abilities
+ */
+@Injectable()
+export class AbilitiesGuard implements CanActivate {
+ constructor(
+ private reflector: Reflector,
+ private abilityFactory: AbilityFactory,
+ ) {}
+
+ async canActivate(context: ExecutionContext): boolean {
+ const requiredPermissions =
+ this.reflector.get(
+ CHECK_ABILITY,
+ context.getHandler(),
+ ) || [];
+
+ // If no permissions required, allow access
+ if (requiredPermissions.length === 0) {
+ return true;
+ }
+
+ const request = context.switchToHttp().getRequest();
+ const user = request.user;
+
+ // User should be attached by JwtAuthGuard
+ if (!user) {
+ throw new ForbiddenException('User not authenticated');
+ }
+
+ // Build abilities for user
+ const ability = this.abilityFactory.defineAbilitiesFor(user);
+
+ // Check if user has all required permissions
+ const hasPermission = requiredPermissions.every((permission) =>
+ ability.can(permission.action, permission.subject),
+ );
+
+ if (!hasPermission) {
+ throw new ForbiddenException(
+ `User does not have required permissions`,
+ );
+ }
+
+ return true;
+ }
+}
diff --git a/backend/src/auth/guards/jwt-auth.guard.ts b/backend/src/auth/guards/jwt-auth.guard.ts
new file mode 100644
index 0000000..18da8bd
--- /dev/null
+++ b/backend/src/auth/guards/jwt-auth.guard.ts
@@ -0,0 +1,25 @@
+import { Injectable, ExecutionContext } from '@nestjs/common';
+import { Reflector } from '@nestjs/core';
+import { AuthGuard } from '@nestjs/passport';
+import { IS_PUBLIC_KEY } from '../decorators/public.decorator';
+
+@Injectable()
+export class JwtAuthGuard extends AuthGuard('jwt') {
+ constructor(private reflector: Reflector) {
+ super();
+ }
+
+ canActivate(context: ExecutionContext) {
+ // Check if route is marked as public
+ const isPublic = this.reflector.getAllAndOverride(IS_PUBLIC_KEY, [
+ context.getHandler(),
+ context.getClass(),
+ ]);
+
+ if (isPublic) {
+ return true;
+ }
+
+ return super.canActivate(context);
+ }
+}
diff --git a/backend/src/auth/guards/roles.guard.ts b/backend/src/auth/guards/roles.guard.ts
new file mode 100644
index 0000000..178d050
--- /dev/null
+++ b/backend/src/auth/guards/roles.guard.ts
@@ -0,0 +1,23 @@
+import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
+import { Reflector } from '@nestjs/core';
+import { Role } from '@prisma/client';
+import { ROLES_KEY } from '../decorators/roles.decorator';
+
+@Injectable()
+export class RolesGuard implements CanActivate {
+ constructor(private reflector: Reflector) {}
+
+ canActivate(context: ExecutionContext): boolean {
+ const requiredRoles = this.reflector.getAllAndOverride(ROLES_KEY, [
+ context.getHandler(),
+ context.getClass(),
+ ]);
+
+ if (!requiredRoles) {
+ return true;
+ }
+
+ const { user } = context.switchToHttp().getRequest();
+ return requiredRoles.some((role) => user.role === role);
+ }
+}
diff --git a/backend/src/auth/strategies/jwt.strategy.ts b/backend/src/auth/strategies/jwt.strategy.ts
new file mode 100644
index 0000000..33709dd
--- /dev/null
+++ b/backend/src/auth/strategies/jwt.strategy.ts
@@ -0,0 +1,75 @@
+import { Injectable, UnauthorizedException, Logger } from '@nestjs/common';
+import { PassportStrategy } from '@nestjs/passport';
+import { ConfigService } from '@nestjs/config';
+import { Strategy, ExtractJwt } from 'passport-jwt';
+import { passportJwtSecret } from 'jwks-rsa';
+import { AuthService } from '../auth.service';
+import { HttpService } from '@nestjs/axios';
+import { firstValueFrom } from 'rxjs';
+
+@Injectable()
+export class JwtStrategy extends PassportStrategy(Strategy) {
+ private readonly logger = new Logger(JwtStrategy.name);
+
+ constructor(
+ private configService: ConfigService,
+ private authService: AuthService,
+ private httpService: HttpService,
+ ) {
+ super({
+ secretOrKeyProvider: passportJwtSecret({
+ cache: true,
+ rateLimit: true,
+ jwksRequestsPerMinute: 5,
+ jwksUri: `${configService.get('AUTH0_ISSUER')}.well-known/jwks.json`,
+ }),
+ jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
+ audience: configService.get('AUTH0_AUDIENCE'),
+ issuer: configService.get('AUTH0_ISSUER'),
+ algorithms: ['RS256'],
+ passReqToCallback: true, // We need the request to get the token
+ });
+ }
+
+ async validate(req: any, payload: any) {
+ // Extract token from Authorization header
+ const token = req.headers.authorization?.replace('Bearer ', '');
+
+ // Fetch user info from Auth0 /userinfo endpoint
+ try {
+ const userInfoUrl = `${this.configService.get('AUTH0_ISSUER')}userinfo`;
+
+ const response = await firstValueFrom(
+ this.httpService.get(userInfoUrl, {
+ headers: {
+ Authorization: `Bearer ${token}`,
+ },
+ }),
+ );
+
+ // Merge userinfo data into payload
+ const userInfo = response.data;
+
+ payload.email = userInfo.email || payload.email;
+ payload.name = userInfo.name || payload.name;
+ payload.picture = userInfo.picture || payload.picture;
+ payload.email_verified = userInfo.email_verified;
+ } catch (error) {
+ this.logger.warn(`Failed to fetch user info: ${error.message}`);
+ // Continue with payload-only data (fallbacks will apply)
+ }
+
+ // Get or create user from Auth0 token
+ const user = await this.authService.validateUser(payload);
+
+ if (!user) {
+ throw new UnauthorizedException('User not found');
+ }
+
+ if (!user.isApproved) {
+ throw new UnauthorizedException('User account pending approval');
+ }
+
+ return user;
+ }
+}
diff --git a/backend/src/common/filters/all-exceptions.filter.ts b/backend/src/common/filters/all-exceptions.filter.ts
new file mode 100644
index 0000000..1322fd6
--- /dev/null
+++ b/backend/src/common/filters/all-exceptions.filter.ts
@@ -0,0 +1,63 @@
+import {
+ ExceptionFilter,
+ Catch,
+ ArgumentsHost,
+ HttpException,
+ HttpStatus,
+ Logger,
+} from '@nestjs/common';
+import { Request, Response } from 'express';
+
+/**
+ * Catch-all exception filter for unhandled errors
+ * This ensures all errors return a consistent format
+ */
+@Catch()
+export class AllExceptionsFilter implements ExceptionFilter {
+ private readonly logger = new Logger(AllExceptionsFilter.name);
+
+ catch(exception: unknown, host: ArgumentsHost) {
+ const ctx = host.switchToHttp();
+ const response = ctx.getResponse();
+ const request = ctx.getRequest();
+
+ let status = HttpStatus.INTERNAL_SERVER_ERROR;
+ let message = 'Internal server error';
+ let stack: string | undefined;
+
+ if (exception instanceof HttpException) {
+ status = exception.getStatus();
+ const exceptionResponse = exception.getResponse();
+ message =
+ typeof exceptionResponse === 'string'
+ ? exceptionResponse
+ : (exceptionResponse as any).message || exception.message;
+ stack = exception.stack;
+ } else if (exception instanceof Error) {
+ message = exception.message;
+ stack = exception.stack;
+ }
+
+ const errorResponse = {
+ statusCode: status,
+ timestamp: new Date().toISOString(),
+ path: request.url,
+ method: request.method,
+ message,
+ error: HttpStatus[status],
+ };
+
+ // Log the error
+ this.logger.error(
+ `[${request.method}] ${request.url} - ${status} - ${message}`,
+ stack,
+ );
+
+ // In development, include stack trace in response
+ if (process.env.NODE_ENV === 'development' && stack) {
+ (errorResponse as any).stack = stack;
+ }
+
+ response.status(status).json(errorResponse);
+ }
+}
diff --git a/backend/src/common/filters/http-exception.filter.ts b/backend/src/common/filters/http-exception.filter.ts
new file mode 100644
index 0000000..6ba0df5
--- /dev/null
+++ b/backend/src/common/filters/http-exception.filter.ts
@@ -0,0 +1,88 @@
+import {
+ ExceptionFilter,
+ Catch,
+ ArgumentsHost,
+ HttpException,
+ HttpStatus,
+ Logger,
+} from '@nestjs/common';
+import { Request, Response } from 'express';
+
+/**
+ * Global exception filter that catches all HTTP exceptions
+ * and formats them consistently with proper logging
+ */
+@Catch(HttpException)
+export class HttpExceptionFilter implements ExceptionFilter {
+ private readonly logger = new Logger(HttpExceptionFilter.name);
+
+ catch(exception: HttpException, host: ArgumentsHost) {
+ const ctx = host.switchToHttp();
+ const response = ctx.getResponse();
+ const request = ctx.getRequest();
+ const status = exception.getStatus();
+ const exceptionResponse = exception.getResponse();
+
+ // Extract error details
+ const errorDetails =
+ typeof exceptionResponse === 'string'
+ ? { message: exceptionResponse }
+ : (exceptionResponse as any);
+
+ // Build standardized error response
+ const errorResponse = {
+ statusCode: status,
+ timestamp: new Date().toISOString(),
+ path: request.url,
+ method: request.method,
+ message: errorDetails.message || exception.message,
+ error: errorDetails.error || HttpStatus[status],
+ ...(errorDetails.details && { details: errorDetails.details }),
+ ...(errorDetails.conflicts && { conflicts: errorDetails.conflicts }),
+ };
+
+ // Log error with appropriate level
+ const logMessage = `[${request.method}] ${request.url} - ${status} - ${errorResponse.message}`;
+
+ if (status >= 500) {
+ this.logger.error(logMessage, exception.stack);
+ } else if (status >= 400) {
+ this.logger.warn(logMessage);
+ } else {
+ this.logger.log(logMessage);
+ }
+
+ // Log request details for debugging (exclude sensitive data)
+ if (status >= 400) {
+ const sanitizedBody = this.sanitizeRequestBody(request.body);
+ this.logger.debug(
+ `Request details: ${JSON.stringify({
+ params: request.params,
+ query: request.query,
+ body: sanitizedBody,
+ user: (request as any).user?.email,
+ })}`,
+ );
+ }
+
+ response.status(status).json(errorResponse);
+ }
+
+ /**
+ * Remove sensitive fields from request body before logging
+ */
+ private sanitizeRequestBody(body: any): any {
+ if (!body) return body;
+
+ const sensitiveFields = ['password', 'token', 'apiKey', 'secret'];
+ const sanitized = { ...body };
+
+ sensitiveFields.forEach((field) => {
+ if (sanitized[field]) {
+ sanitized[field] = '***REDACTED***';
+ }
+ });
+
+ return sanitized;
+ }
+}
diff --git a/backend/src/common/filters/index.ts b/backend/src/common/filters/index.ts
new file mode 100644
index 0000000..b90b0b2
--- /dev/null
+++ b/backend/src/common/filters/index.ts
@@ -0,0 +1,2 @@
+export * from './http-exception.filter';
+export * from './all-exceptions.filter';
diff --git a/backend/src/config/simpleAuth.ts b/backend/src/config/simpleAuth.ts
deleted file mode 100644
index 28de296..0000000
--- a/backend/src/config/simpleAuth.ts
+++ /dev/null
@@ -1,236 +0,0 @@
-import jwtKeyManager, { User } from '../services/jwtKeyManager';
-
-// JWT Key Manager now handles all token operations with automatic rotation
-// No more static JWT_SECRET needed!
-
-export { User } from '../services/jwtKeyManager';
-
-export function generateToken(user: User): string {
- return jwtKeyManager.generateToken(user);
-}
-
-export function verifyToken(token: string): User | null {
- return jwtKeyManager.verifyToken(token);
-}
-
-// Simple Google OAuth2 client using fetch
-export async function verifyGoogleToken(googleToken: string): Promise {
- try {
- const response = await fetch(`https://www.googleapis.com/oauth2/v1/userinfo?access_token=${googleToken}`);
- if (!response.ok) {
- throw new Error('Invalid Google token');
- }
- return await response.json();
- } catch (error) {
- console.error('Error verifying Google token:', error);
- return null;
- }
-}
-
-// Get Google OAuth2 URL
-export function getGoogleAuthUrl(): string {
- const clientId = process.env.GOOGLE_CLIENT_ID;
- const redirectUri = process.env.GOOGLE_REDIRECT_URI || 'http://localhost:3000/auth/google/callback';
-
- console.log('🔗 Generating Google OAuth URL:', {
- client_id_present: !!clientId,
- redirect_uri: redirectUri,
- environment: process.env.NODE_ENV || 'development'
- });
-
- if (!clientId) {
- console.error('❌ GOOGLE_CLIENT_ID not configured');
- throw new Error('GOOGLE_CLIENT_ID not configured');
- }
-
- if (!redirectUri.startsWith('http')) {
- console.error('❌ Invalid redirect URI:', redirectUri);
- throw new Error('GOOGLE_REDIRECT_URI must be a valid HTTP/HTTPS URL');
- }
-
- const params = new URLSearchParams({
- client_id: clientId,
- redirect_uri: redirectUri,
- response_type: 'code',
- scope: 'openid email profile',
- access_type: 'offline',
- prompt: 'consent'
- });
-
- const authUrl = `https://accounts.google.com/o/oauth2/v2/auth?${params.toString()}`;
- console.log('✅ Google OAuth URL generated successfully');
-
- return authUrl;
-}
-
-// Exchange authorization code for tokens
-export async function exchangeCodeForTokens(code: string): Promise {
- const clientId = process.env.GOOGLE_CLIENT_ID;
- const clientSecret = process.env.GOOGLE_CLIENT_SECRET;
- const redirectUri = process.env.GOOGLE_REDIRECT_URI || 'http://localhost:3000/auth/google/callback';
-
- console.log('🔄 Exchanging OAuth code for tokens:', {
- client_id_present: !!clientId,
- client_secret_present: !!clientSecret,
- redirect_uri: redirectUri,
- code_length: code?.length || 0
- });
-
- if (!clientId || !clientSecret) {
- console.error('❌ Google OAuth credentials not configured:', {
- client_id: !!clientId,
- client_secret: !!clientSecret
- });
- throw new Error('Google OAuth credentials not configured');
- }
-
- if (!code || code.length < 10) {
- console.error('❌ Invalid authorization code:', { code_length: code?.length || 0 });
- throw new Error('Invalid authorization code provided');
- }
-
- try {
- const tokenUrl = 'https://oauth2.googleapis.com/token';
- const requestBody = new URLSearchParams({
- client_id: clientId,
- client_secret: clientSecret,
- code,
- grant_type: 'authorization_code',
- redirect_uri: redirectUri,
- });
-
- console.log('📡 Making token exchange request to Google:', {
- url: tokenUrl,
- redirect_uri: redirectUri,
- grant_type: 'authorization_code'
- });
-
- const response = await fetch(tokenUrl, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/x-www-form-urlencoded',
- 'Accept': 'application/json'
- },
- body: requestBody,
- });
-
- const responseText = await response.text();
-
- console.log('📨 Token exchange response:', {
- status: response.status,
- ok: response.ok,
- content_type: response.headers.get('content-type'),
- response_length: responseText.length
- });
-
- if (!response.ok) {
- console.error('❌ Token exchange failed:', {
- status: response.status,
- statusText: response.statusText,
- response: responseText
- });
- throw new Error(`Failed to exchange code for tokens: ${response.status} ${response.statusText}`);
- }
-
- let tokenData;
- try {
- tokenData = JSON.parse(responseText);
- } catch (parseError) {
- console.error('❌ Failed to parse token response:', { response: responseText });
- throw new Error('Invalid JSON response from Google token endpoint');
- }
-
- if (!tokenData.access_token) {
- console.error('❌ No access token in response:', tokenData);
- throw new Error('No access token received from Google');
- }
-
- console.log('✅ Token exchange successful:', {
- has_access_token: !!tokenData.access_token,
- has_refresh_token: !!tokenData.refresh_token,
- token_type: tokenData.token_type,
- expires_in: tokenData.expires_in
- });
-
- return tokenData;
- } catch (error) {
- console.error('❌ Error exchanging code for tokens:', {
- error: error instanceof Error ? error.message : 'Unknown error',
- stack: error instanceof Error ? error.stack : undefined
- });
- throw error;
- }
-}
-
-// Get user info from Google
-export async function getGoogleUserInfo(accessToken: string): Promise {
- console.log('👤 Getting user info from Google:', {
- token_length: accessToken?.length || 0,
- token_prefix: accessToken ? accessToken.substring(0, 10) + '...' : 'none'
- });
-
- if (!accessToken || accessToken.length < 10) {
- console.error('❌ Invalid access token for user info request');
- throw new Error('Invalid access token provided');
- }
-
- try {
- const userInfoUrl = `https://www.googleapis.com/oauth2/v2/userinfo?access_token=${accessToken}`;
-
- console.log('📡 Making user info request to Google');
-
- const response = await fetch(userInfoUrl, {
- method: 'GET',
- headers: {
- 'Accept': 'application/json',
- 'Authorization': `Bearer ${accessToken}`
- }
- });
-
- const responseText = await response.text();
-
- console.log('📨 User info response:', {
- status: response.status,
- ok: response.ok,
- content_type: response.headers.get('content-type'),
- response_length: responseText.length
- });
-
- if (!response.ok) {
- console.error('❌ Failed to get user info:', {
- status: response.status,
- statusText: response.statusText,
- response: responseText
- });
- throw new Error(`Failed to get user info: ${response.status} ${response.statusText}`);
- }
-
- let userData;
- try {
- userData = JSON.parse(responseText);
- } catch (parseError) {
- console.error('❌ Failed to parse user info response:', { response: responseText });
- throw new Error('Invalid JSON response from Google user info endpoint');
- }
-
- if (!userData.email) {
- console.error('❌ No email in user info response:', userData);
- throw new Error('No email address received from Google');
- }
-
- console.log('✅ User info retrieved successfully:', {
- email: userData.email,
- name: userData.name,
- verified_email: userData.verified_email,
- has_picture: !!userData.picture
- });
-
- return userData;
- } catch (error) {
- console.error('❌ Error getting Google user info:', {
- error: error instanceof Error ? error.message : 'Unknown error',
- stack: error instanceof Error ? error.stack : undefined
- });
- throw error;
- }
-}
diff --git a/backend/src/drivers/drivers.controller.ts b/backend/src/drivers/drivers.controller.ts
new file mode 100644
index 0000000..7ab635e
--- /dev/null
+++ b/backend/src/drivers/drivers.controller.ts
@@ -0,0 +1,63 @@
+import {
+ Controller,
+ Get,
+ Post,
+ Patch,
+ Delete,
+ Body,
+ Param,
+ Query,
+ UseGuards,
+} from '@nestjs/common';
+import { DriversService } from './drivers.service';
+import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
+import { RolesGuard } from '../auth/guards/roles.guard';
+import { Roles } from '../auth/decorators/roles.decorator';
+import { Role } from '@prisma/client';
+import { CreateDriverDto, UpdateDriverDto } from './dto';
+
+@Controller('drivers')
+@UseGuards(JwtAuthGuard, RolesGuard)
+export class DriversController {
+ constructor(private readonly driversService: DriversService) {}
+
+ @Post()
+ @Roles(Role.ADMINISTRATOR, Role.COORDINATOR)
+ create(@Body() createDriverDto: CreateDriverDto) {
+ return this.driversService.create(createDriverDto);
+ }
+
+ @Get()
+ @Roles(Role.ADMINISTRATOR, Role.COORDINATOR, Role.DRIVER)
+ findAll() {
+ return this.driversService.findAll();
+ }
+
+ @Get(':id')
+ @Roles(Role.ADMINISTRATOR, Role.COORDINATOR, Role.DRIVER)
+ findOne(@Param('id') id: string) {
+ return this.driversService.findOne(id);
+ }
+
+ @Get(':id/schedule')
+ @Roles(Role.ADMINISTRATOR, Role.COORDINATOR, Role.DRIVER)
+ getSchedule(@Param('id') id: string) {
+ return this.driversService.getSchedule(id);
+ }
+
+ @Patch(':id')
+ @Roles(Role.ADMINISTRATOR, Role.COORDINATOR)
+ update(@Param('id') id: string, @Body() updateDriverDto: UpdateDriverDto) {
+ return this.driversService.update(id, updateDriverDto);
+ }
+
+ @Delete(':id')
+ @Roles(Role.ADMINISTRATOR, Role.COORDINATOR)
+ remove(
+ @Param('id') id: string,
+ @Query('hard') hard?: string,
+ ) {
+ const isHardDelete = hard === 'true';
+ return this.driversService.remove(id, isHardDelete);
+ }
+}
diff --git a/backend/src/drivers/drivers.module.ts b/backend/src/drivers/drivers.module.ts
new file mode 100644
index 0000000..c4ccb65
--- /dev/null
+++ b/backend/src/drivers/drivers.module.ts
@@ -0,0 +1,10 @@
+import { Module } from '@nestjs/common';
+import { DriversController } from './drivers.controller';
+import { DriversService } from './drivers.service';
+
+@Module({
+ controllers: [DriversController],
+ providers: [DriversService],
+ exports: [DriversService],
+})
+export class DriversModule {}
diff --git a/backend/src/drivers/drivers.service.ts b/backend/src/drivers/drivers.service.ts
new file mode 100644
index 0000000..c84fb4a
--- /dev/null
+++ b/backend/src/drivers/drivers.service.ts
@@ -0,0 +1,89 @@
+import { Injectable, NotFoundException, Logger } from '@nestjs/common';
+import { PrismaService } from '../prisma/prisma.service';
+import { CreateDriverDto, UpdateDriverDto } from './dto';
+
+@Injectable()
+export class DriversService {
+ private readonly logger = new Logger(DriversService.name);
+
+ constructor(private prisma: PrismaService) {}
+
+ async create(createDriverDto: CreateDriverDto) {
+ this.logger.log(`Creating driver: ${createDriverDto.name}`);
+
+ return this.prisma.driver.create({
+ data: createDriverDto,
+ include: { user: true },
+ });
+ }
+
+ async findAll() {
+ return this.prisma.driver.findMany({
+ where: { deletedAt: null },
+ include: {
+ user: true,
+ events: {
+ where: { deletedAt: null },
+ include: { vip: true },
+ orderBy: { startTime: 'asc' },
+ },
+ },
+ orderBy: { name: 'asc' },
+ });
+ }
+
+ async findOne(id: string) {
+ const driver = await this.prisma.driver.findFirst({
+ where: { id, deletedAt: null },
+ include: {
+ user: true,
+ events: {
+ where: { deletedAt: null },
+ include: { vip: true },
+ orderBy: { startTime: 'asc' },
+ },
+ },
+ });
+
+ if (!driver) {
+ throw new NotFoundException(`Driver with ID ${id} not found`);
+ }
+
+ return driver;
+ }
+
+ async update(id: string, updateDriverDto: UpdateDriverDto) {
+ const driver = await this.findOne(id);
+
+ this.logger.log(`Updating driver ${id}: ${driver.name}`);
+
+ return this.prisma.driver.update({
+ where: { id: driver.id },
+ data: updateDriverDto,
+ include: { user: true },
+ });
+ }
+
+ async remove(id: string, hardDelete = false) {
+ const driver = await this.findOne(id);
+
+ if (hardDelete) {
+ this.logger.log(`Hard deleting driver: ${driver.name}`);
+ return this.prisma.driver.delete({
+ where: { id: driver.id },
+ });
+ }
+
+ this.logger.log(`Soft deleting driver: ${driver.name}`);
+ return this.prisma.driver.update({
+ where: { id: driver.id },
+ data: { deletedAt: new Date() },
+ });
+ }
+
+ async getSchedule(id: string) {
+ const driver = await this.findOne(id);
+
+ return driver.events;
+ }
+}
diff --git a/backend/src/drivers/dto/create-driver.dto.ts b/backend/src/drivers/dto/create-driver.dto.ts
new file mode 100644
index 0000000..4ecf000
--- /dev/null
+++ b/backend/src/drivers/dto/create-driver.dto.ts
@@ -0,0 +1,18 @@
+import { IsString, IsEnum, IsOptional, IsUUID } from 'class-validator';
+import { Department } from '@prisma/client';
+
+export class CreateDriverDto {
+ @IsString()
+ name: string;
+
+ @IsString()
+ phone: string;
+
+ @IsEnum(Department)
+ @IsOptional()
+ department?: Department;
+
+ @IsUUID()
+ @IsOptional()
+ userId?: string;
+}
diff --git a/backend/src/drivers/dto/index.ts b/backend/src/drivers/dto/index.ts
new file mode 100644
index 0000000..a87cc04
--- /dev/null
+++ b/backend/src/drivers/dto/index.ts
@@ -0,0 +1,2 @@
+export * from './create-driver.dto';
+export * from './update-driver.dto';
diff --git a/backend/src/drivers/dto/update-driver.dto.ts b/backend/src/drivers/dto/update-driver.dto.ts
new file mode 100644
index 0000000..f44e541
--- /dev/null
+++ b/backend/src/drivers/dto/update-driver.dto.ts
@@ -0,0 +1,4 @@
+import { PartialType } from '@nestjs/mapped-types';
+import { CreateDriverDto } from './create-driver.dto';
+
+export class UpdateDriverDto extends PartialType(CreateDriverDto) {}
diff --git a/backend/src/events/dto/create-event.dto.ts b/backend/src/events/dto/create-event.dto.ts
new file mode 100644
index 0000000..4f08df6
--- /dev/null
+++ b/backend/src/events/dto/create-event.dto.ts
@@ -0,0 +1,58 @@
+import {
+ IsString,
+ IsEnum,
+ IsOptional,
+ IsUUID,
+ IsDateString,
+} from 'class-validator';
+import { EventType, EventStatus } from '@prisma/client';
+
+export class CreateEventDto {
+ @IsUUID()
+ vipId: string;
+
+ @IsString()
+ title: string;
+
+ @IsString()
+ @IsOptional()
+ location?: string;
+
+ @IsString()
+ @IsOptional()
+ pickupLocation?: string;
+
+ @IsString()
+ @IsOptional()
+ dropoffLocation?: string;
+
+ @IsDateString()
+ startTime: string;
+
+ @IsDateString()
+ endTime: string;
+
+ @IsString()
+ @IsOptional()
+ description?: string;
+
+ @IsString()
+ @IsOptional()
+ notes?: string;
+
+ @IsEnum(EventType)
+ @IsOptional()
+ type?: EventType;
+
+ @IsEnum(EventStatus)
+ @IsOptional()
+ status?: EventStatus;
+
+ @IsUUID()
+ @IsOptional()
+ driverId?: string;
+
+ @IsUUID()
+ @IsOptional()
+ vehicleId?: string;
+}
diff --git a/backend/src/events/dto/index.ts b/backend/src/events/dto/index.ts
new file mode 100644
index 0000000..5dfd4e8
--- /dev/null
+++ b/backend/src/events/dto/index.ts
@@ -0,0 +1,3 @@
+export * from './create-event.dto';
+export * from './update-event.dto';
+export * from './update-event-status.dto';
diff --git a/backend/src/events/dto/update-event-status.dto.ts b/backend/src/events/dto/update-event-status.dto.ts
new file mode 100644
index 0000000..2a6ba93
--- /dev/null
+++ b/backend/src/events/dto/update-event-status.dto.ts
@@ -0,0 +1,7 @@
+import { IsEnum } from 'class-validator';
+import { EventStatus } from '@prisma/client';
+
+export class UpdateEventStatusDto {
+ @IsEnum(EventStatus)
+ status: EventStatus;
+}
diff --git a/backend/src/events/dto/update-event.dto.ts b/backend/src/events/dto/update-event.dto.ts
new file mode 100644
index 0000000..304f950
--- /dev/null
+++ b/backend/src/events/dto/update-event.dto.ts
@@ -0,0 +1,4 @@
+import { PartialType } from '@nestjs/mapped-types';
+import { CreateEventDto } from './create-event.dto';
+
+export class UpdateEventDto extends PartialType(CreateEventDto) {}
diff --git a/backend/src/events/events.controller.ts b/backend/src/events/events.controller.ts
new file mode 100644
index 0000000..59d20de
--- /dev/null
+++ b/backend/src/events/events.controller.ts
@@ -0,0 +1,66 @@
+import {
+ Controller,
+ Get,
+ Post,
+ Patch,
+ Delete,
+ Body,
+ Param,
+ Query,
+ UseGuards,
+} from '@nestjs/common';
+import { EventsService } from './events.service';
+import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
+import { RolesGuard } from '../auth/guards/roles.guard';
+import { Roles } from '../auth/decorators/roles.decorator';
+import { Role } from '@prisma/client';
+import { CreateEventDto, UpdateEventDto, UpdateEventStatusDto } from './dto';
+
+@Controller('events')
+@UseGuards(JwtAuthGuard, RolesGuard)
+export class EventsController {
+ constructor(private readonly eventsService: EventsService) {}
+
+ @Post()
+ @Roles(Role.ADMINISTRATOR, Role.COORDINATOR)
+ create(@Body() createEventDto: CreateEventDto) {
+ return this.eventsService.create(createEventDto);
+ }
+
+ @Get()
+ @Roles(Role.ADMINISTRATOR, Role.COORDINATOR, Role.DRIVER)
+ findAll() {
+ return this.eventsService.findAll();
+ }
+
+ @Get(':id')
+ @Roles(Role.ADMINISTRATOR, Role.COORDINATOR, Role.DRIVER)
+ findOne(@Param('id') id: string) {
+ return this.eventsService.findOne(id);
+ }
+
+ @Patch(':id')
+ @Roles(Role.ADMINISTRATOR, Role.COORDINATOR)
+ update(@Param('id') id: string, @Body() updateEventDto: UpdateEventDto) {
+ return this.eventsService.update(id, updateEventDto);
+ }
+
+ @Patch(':id/status')
+ @Roles(Role.ADMINISTRATOR, Role.COORDINATOR, Role.DRIVER)
+ updateStatus(
+ @Param('id') id: string,
+ @Body() updateEventStatusDto: UpdateEventStatusDto,
+ ) {
+ return this.eventsService.updateStatus(id, updateEventStatusDto);
+ }
+
+ @Delete(':id')
+ @Roles(Role.ADMINISTRATOR, Role.COORDINATOR)
+ remove(
+ @Param('id') id: string,
+ @Query('hard') hard?: string,
+ ) {
+ const isHardDelete = hard === 'true';
+ return this.eventsService.remove(id, isHardDelete);
+ }
+}
diff --git a/backend/src/events/events.module.ts b/backend/src/events/events.module.ts
new file mode 100644
index 0000000..bc2a1fc
--- /dev/null
+++ b/backend/src/events/events.module.ts
@@ -0,0 +1,10 @@
+import { Module } from '@nestjs/common';
+import { EventsController } from './events.controller';
+import { EventsService } from './events.service';
+
+@Module({
+ controllers: [EventsController],
+ providers: [EventsService],
+ exports: [EventsService],
+})
+export class EventsModule {}
diff --git a/backend/src/events/events.service.ts b/backend/src/events/events.service.ts
new file mode 100644
index 0000000..d3dbd52
--- /dev/null
+++ b/backend/src/events/events.service.ts
@@ -0,0 +1,222 @@
+import {
+ Injectable,
+ NotFoundException,
+ BadRequestException,
+ Logger,
+} from '@nestjs/common';
+import { PrismaService } from '../prisma/prisma.service';
+import { CreateEventDto, UpdateEventDto, UpdateEventStatusDto } from './dto';
+
+@Injectable()
+export class EventsService {
+ private readonly logger = new Logger(EventsService.name);
+
+ constructor(private prisma: PrismaService) {}
+
+ async create(createEventDto: CreateEventDto) {
+ this.logger.log(`Creating event: ${createEventDto.title}`);
+
+ // Check for conflicts if driver is assigned
+ if (createEventDto.driverId) {
+ const conflicts = await this.checkConflicts(
+ createEventDto.driverId,
+ new Date(createEventDto.startTime),
+ new Date(createEventDto.endTime),
+ );
+
+ if (conflicts.length > 0) {
+ this.logger.warn(
+ `Conflict detected for driver ${createEventDto.driverId}`,
+ );
+ throw new BadRequestException({
+ message: 'Driver has conflicting events',
+ conflicts: conflicts.map((e) => ({
+ id: e.id,
+ title: e.title,
+ startTime: e.startTime,
+ endTime: e.endTime,
+ })),
+ });
+ }
+ }
+
+ return this.prisma.scheduleEvent.create({
+ data: {
+ ...createEventDto,
+ startTime: new Date(createEventDto.startTime),
+ endTime: new Date(createEventDto.endTime),
+ },
+ include: {
+ vip: true,
+ driver: true,
+ vehicle: true,
+ },
+ });
+ }
+
+ async findAll() {
+ return this.prisma.scheduleEvent.findMany({
+ where: { deletedAt: null },
+ include: {
+ vip: true,
+ driver: true,
+ vehicle: true,
+ },
+ orderBy: { startTime: 'asc' },
+ });
+ }
+
+ async findOne(id: string) {
+ const event = await this.prisma.scheduleEvent.findFirst({
+ where: { id, deletedAt: null },
+ include: {
+ vip: true,
+ driver: true,
+ vehicle: true,
+ },
+ });
+
+ if (!event) {
+ throw new NotFoundException(`Event with ID ${id} not found`);
+ }
+
+ return event;
+ }
+
+ async update(id: string, updateEventDto: UpdateEventDto) {
+ const event = await this.findOne(id);
+
+ // Check for conflicts if driver or times are being updated
+ if (
+ updateEventDto.driverId ||
+ updateEventDto.startTime ||
+ updateEventDto.endTime
+ ) {
+ const driverId = updateEventDto.driverId || event.driverId;
+ const startTime = updateEventDto.startTime
+ ? new Date(updateEventDto.startTime)
+ : event.startTime;
+ const endTime = updateEventDto.endTime
+ ? new Date(updateEventDto.endTime)
+ : event.endTime;
+
+ if (driverId) {
+ const conflicts = await this.checkConflicts(
+ driverId,
+ startTime,
+ endTime,
+ event.id, // Exclude current event from conflict check
+ );
+
+ if (conflicts.length > 0) {
+ this.logger.warn(`Conflict detected for driver ${driverId}`);
+ throw new BadRequestException({
+ message: 'Driver has conflicting events',
+ conflicts: conflicts.map((e) => ({
+ id: e.id,
+ title: e.title,
+ startTime: e.startTime,
+ endTime: e.endTime,
+ })),
+ });
+ }
+ }
+ }
+
+ this.logger.log(`Updating event ${id}: ${event.title}`);
+
+ const updateData: any = { ...updateEventDto };
+ if (updateEventDto.startTime) {
+ updateData.startTime = new Date(updateEventDto.startTime);
+ }
+ if (updateEventDto.endTime) {
+ updateData.endTime = new Date(updateEventDto.endTime);
+ }
+
+ return this.prisma.scheduleEvent.update({
+ where: { id: event.id },
+ data: updateData,
+ include: {
+ vip: true,
+ driver: true,
+ vehicle: true,
+ },
+ });
+ }
+
+ async updateStatus(id: string, updateEventStatusDto: UpdateEventStatusDto) {
+ const event = await this.findOne(id);
+
+ this.logger.log(
+ `Updating event status ${id}: ${event.title} -> ${updateEventStatusDto.status}`,
+ );
+
+ return this.prisma.scheduleEvent.update({
+ where: { id: event.id },
+ data: { status: updateEventStatusDto.status },
+ include: {
+ vip: true,
+ driver: true,
+ vehicle: true,
+ },
+ });
+ }
+
+ async remove(id: string, hardDelete = false) {
+ const event = await this.findOne(id);
+
+ if (hardDelete) {
+ this.logger.log(`Hard deleting event: ${event.title}`);
+ return this.prisma.scheduleEvent.delete({
+ where: { id: event.id },
+ });
+ }
+
+ this.logger.log(`Soft deleting event: ${event.title}`);
+ return this.prisma.scheduleEvent.update({
+ where: { id: event.id },
+ data: { deletedAt: new Date() },
+ });
+ }
+
+ /**
+ * Check for conflicting events for a driver
+ */
+ private async checkConflicts(
+ driverId: string,
+ startTime: Date,
+ endTime: Date,
+ excludeEventId?: string,
+ ) {
+ return this.prisma.scheduleEvent.findMany({
+ where: {
+ driverId,
+ deletedAt: null,
+ id: excludeEventId ? { not: excludeEventId } : undefined,
+ OR: [
+ {
+ // New event starts during existing event
+ AND: [
+ { startTime: { lte: startTime } },
+ { endTime: { gt: startTime } },
+ ],
+ },
+ {
+ // New event ends during existing event
+ AND: [
+ { startTime: { lt: endTime } },
+ { endTime: { gte: endTime } },
+ ],
+ },
+ {
+ // New event completely contains existing event
+ AND: [
+ { startTime: { gte: startTime } },
+ { endTime: { lte: endTime } },
+ ],
+ },
+ ],
+ },
+ });
+ }
+}
diff --git a/backend/src/flights/dto/create-flight.dto.ts b/backend/src/flights/dto/create-flight.dto.ts
new file mode 100644
index 0000000..662526c
--- /dev/null
+++ b/backend/src/flights/dto/create-flight.dto.ts
@@ -0,0 +1,42 @@
+import { IsString, IsDateString, IsInt, IsUUID, IsOptional } from 'class-validator';
+
+export class CreateFlightDto {
+ @IsUUID()
+ vipId: string;
+
+ @IsString()
+ flightNumber: string;
+
+ @IsDateString()
+ flightDate: string;
+
+ @IsInt()
+ @IsOptional()
+ segment?: number;
+
+ @IsString()
+ departureAirport: string;
+
+ @IsString()
+ arrivalAirport: string;
+
+ @IsDateString()
+ @IsOptional()
+ scheduledDeparture?: string;
+
+ @IsDateString()
+ @IsOptional()
+ scheduledArrival?: string;
+
+ @IsDateString()
+ @IsOptional()
+ actualDeparture?: string;
+
+ @IsDateString()
+ @IsOptional()
+ actualArrival?: string;
+
+ @IsString()
+ @IsOptional()
+ status?: string;
+}
diff --git a/backend/src/flights/dto/index.ts b/backend/src/flights/dto/index.ts
new file mode 100644
index 0000000..64ed28b
--- /dev/null
+++ b/backend/src/flights/dto/index.ts
@@ -0,0 +1,2 @@
+export * from './create-flight.dto';
+export * from './update-flight.dto';
diff --git a/backend/src/flights/dto/update-flight.dto.ts b/backend/src/flights/dto/update-flight.dto.ts
new file mode 100644
index 0000000..5551859
--- /dev/null
+++ b/backend/src/flights/dto/update-flight.dto.ts
@@ -0,0 +1,4 @@
+import { PartialType } from '@nestjs/mapped-types';
+import { CreateFlightDto } from './create-flight.dto';
+
+export class UpdateFlightDto extends PartialType(CreateFlightDto) {}
diff --git a/backend/src/flights/flights.controller.ts b/backend/src/flights/flights.controller.ts
new file mode 100644
index 0000000..62f9a69
--- /dev/null
+++ b/backend/src/flights/flights.controller.ts
@@ -0,0 +1,72 @@
+import {
+ Controller,
+ Get,
+ Post,
+ Patch,
+ Delete,
+ Body,
+ Param,
+ Query,
+ UseGuards,
+} from '@nestjs/common';
+import { FlightsService } from './flights.service';
+import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
+import { RolesGuard } from '../auth/guards/roles.guard';
+import { Roles } from '../auth/decorators/roles.decorator';
+import { Role } from '@prisma/client';
+import { CreateFlightDto, UpdateFlightDto } from './dto';
+
+@Controller('flights')
+@UseGuards(JwtAuthGuard, RolesGuard)
+export class FlightsController {
+ constructor(private readonly flightsService: FlightsService) {}
+
+ @Post()
+ @Roles(Role.ADMINISTRATOR, Role.COORDINATOR)
+ create(@Body() createFlightDto: CreateFlightDto) {
+ return this.flightsService.create(createFlightDto);
+ }
+
+ @Get()
+ @Roles(Role.ADMINISTRATOR, Role.COORDINATOR)
+ findAll() {
+ return this.flightsService.findAll();
+ }
+
+ @Get('status/:flightNumber')
+ @Roles(Role.ADMINISTRATOR, Role.COORDINATOR)
+ getFlightStatus(
+ @Param('flightNumber') flightNumber: string,
+ @Query('date') date?: string,
+ ) {
+ return this.flightsService.getFlightStatus(flightNumber, date);
+ }
+
+ @Get('vip/:vipId')
+ @Roles(Role.ADMINISTRATOR, Role.COORDINATOR)
+ findByVip(@Param('vipId') vipId: string) {
+ return this.flightsService.findByVip(vipId);
+ }
+
+ @Get(':id')
+ @Roles(Role.ADMINISTRATOR, Role.COORDINATOR)
+ findOne(@Param('id') id: string) {
+ return this.flightsService.findOne(id);
+ }
+
+ @Patch(':id')
+ @Roles(Role.ADMINISTRATOR, Role.COORDINATOR)
+ update(@Param('id') id: string, @Body() updateFlightDto: UpdateFlightDto) {
+ return this.flightsService.update(id, updateFlightDto);
+ }
+
+ @Delete(':id')
+ @Roles(Role.ADMINISTRATOR, Role.COORDINATOR)
+ remove(
+ @Param('id') id: string,
+ @Query('hard') hard?: string,
+ ) {
+ const isHardDelete = hard === 'true';
+ return this.flightsService.remove(id, isHardDelete);
+ }
+}
diff --git a/backend/src/flights/flights.module.ts b/backend/src/flights/flights.module.ts
new file mode 100644
index 0000000..171b200
--- /dev/null
+++ b/backend/src/flights/flights.module.ts
@@ -0,0 +1,12 @@
+import { Module } from '@nestjs/common';
+import { HttpModule } from '@nestjs/axios';
+import { FlightsController } from './flights.controller';
+import { FlightsService } from './flights.service';
+
+@Module({
+ imports: [HttpModule],
+ controllers: [FlightsController],
+ providers: [FlightsService],
+ exports: [FlightsService],
+})
+export class FlightsModule {}
diff --git a/backend/src/flights/flights.service.ts b/backend/src/flights/flights.service.ts
new file mode 100644
index 0000000..c96e466
--- /dev/null
+++ b/backend/src/flights/flights.service.ts
@@ -0,0 +1,170 @@
+import { Injectable, Logger, NotFoundException } from '@nestjs/common';
+import { HttpService } from '@nestjs/axios';
+import { ConfigService } from '@nestjs/config';
+import { PrismaService } from '../prisma/prisma.service';
+import { CreateFlightDto, UpdateFlightDto } from './dto';
+import { firstValueFrom } from 'rxjs';
+
+@Injectable()
+export class FlightsService {
+ private readonly logger = new Logger(FlightsService.name);
+ private readonly apiKey: string;
+ private readonly baseUrl = 'http://api.aviationstack.com/v1';
+
+ constructor(
+ private prisma: PrismaService,
+ private httpService: HttpService,
+ private configService: ConfigService,
+ ) {
+ this.apiKey = this.configService.get('AVIATIONSTACK_API_KEY') || '';
+ }
+
+ async create(createFlightDto: CreateFlightDto) {
+ this.logger.log(
+ `Creating flight: ${createFlightDto.flightNumber} for VIP ${createFlightDto.vipId}`,
+ );
+
+ return this.prisma.flight.create({
+ data: {
+ ...createFlightDto,
+ flightDate: new Date(createFlightDto.flightDate),
+ scheduledDeparture: createFlightDto.scheduledDeparture
+ ? new Date(createFlightDto.scheduledDeparture)
+ : undefined,
+ scheduledArrival: createFlightDto.scheduledArrival
+ ? new Date(createFlightDto.scheduledArrival)
+ : undefined,
+ },
+ include: { vip: true },
+ });
+ }
+
+ async findAll() {
+ return this.prisma.flight.findMany({
+ include: { vip: true },
+ orderBy: { flightDate: 'desc' },
+ });
+ }
+
+ async findByVip(vipId: string) {
+ return this.prisma.flight.findMany({
+ where: { vipId },
+ orderBy: [{ flightDate: 'asc' }, { segment: 'asc' }],
+ });
+ }
+
+ async findOne(id: string) {
+ const flight = await this.prisma.flight.findUnique({
+ where: { id },
+ include: { vip: true },
+ });
+
+ if (!flight) {
+ throw new NotFoundException(`Flight with ID ${id} not found`);
+ }
+
+ return flight;
+ }
+
+ async update(id: string, updateFlightDto: UpdateFlightDto) {
+ const flight = await this.findOne(id);
+
+ this.logger.log(`Updating flight ${id}: ${flight.flightNumber}`);
+
+ const updateData: any = { ...updateFlightDto };
+ const dto = updateFlightDto as any; // Type assertion to work around PartialType
+
+ if (dto.flightDate) {
+ updateData.flightDate = new Date(dto.flightDate);
+ }
+ if (dto.scheduledDeparture) {
+ updateData.scheduledDeparture = new Date(dto.scheduledDeparture);
+ }
+ if (dto.scheduledArrival) {
+ updateData.scheduledArrival = new Date(dto.scheduledArrival);
+ }
+ if (dto.actualDeparture) {
+ updateData.actualDeparture = new Date(dto.actualDeparture);
+ }
+ if (dto.actualArrival) {
+ updateData.actualArrival = new Date(dto.actualArrival);
+ }
+
+ return this.prisma.flight.update({
+ where: { id: flight.id },
+ data: updateData,
+ include: { vip: true },
+ });
+ }
+
+ async remove(id: string, hardDelete = false) {
+ const flight = await this.findOne(id);
+
+ this.logger.log(`Deleting flight: ${flight.flightNumber}`);
+
+ // Flights are always hard deleted (no soft delete for flights)
+ return this.prisma.flight.delete({
+ where: { id: flight.id },
+ });
+ }
+
+ /**
+ * Fetch real-time flight status from AviationStack API
+ */
+ async getFlightStatus(flightNumber: string, flightDate?: string) {
+ if (!this.apiKey) {
+ this.logger.warn('AviationStack API key not configured');
+ return {
+ message: 'Flight tracking API not configured',
+ flightNumber,
+ };
+ }
+
+ try {
+ const params: any = {
+ access_key: this.apiKey,
+ flight_iata: flightNumber,
+ };
+
+ if (flightDate) {
+ params.flight_date = flightDate;
+ }
+
+ const response = await firstValueFrom(
+ this.httpService.get(`${this.baseUrl}/flights`, { params }),
+ );
+
+ const data = response.data as any;
+ if (data && data.data && data.data.length > 0) {
+ const flightData = data.data[0];
+
+ return {
+ flightNumber: flightData.flight.iata,
+ status: flightData.flight_status,
+ departure: {
+ airport: flightData.departure.iata,
+ scheduled: flightData.departure.scheduled,
+ actual: flightData.departure.actual,
+ },
+ arrival: {
+ airport: flightData.arrival.iata,
+ scheduled: flightData.arrival.scheduled,
+ estimated: flightData.arrival.estimated,
+ actual: flightData.arrival.actual,
+ },
+ };
+ }
+
+ return {
+ message: 'Flight not found',
+ flightNumber,
+ };
+ } catch (error) {
+ this.logger.error(
+ `Failed to fetch flight status: ${error.message}`,
+ error.stack,
+ );
+ throw error;
+ }
+ }
+}
diff --git a/backend/src/main.ts b/backend/src/main.ts
new file mode 100644
index 0000000..59c2daf
--- /dev/null
+++ b/backend/src/main.ts
@@ -0,0 +1,46 @@
+import { NestFactory } from '@nestjs/core';
+import { ValidationPipe, Logger } from '@nestjs/common';
+import { AppModule } from './app.module';
+import { AllExceptionsFilter, HttpExceptionFilter } from './common/filters';
+
+async function bootstrap() {
+ const logger = new Logger('Bootstrap');
+
+ const app = await NestFactory.create(AppModule);
+
+ // Global prefix for all routes
+ app.setGlobalPrefix('api/v1');
+
+ // Enable CORS
+ app.enableCors({
+ origin: process.env.FRONTEND_URL || 'http://localhost:5173',
+ credentials: true,
+ });
+
+ // Global exception filters (order matters - most specific last)
+ app.useGlobalFilters(
+ new AllExceptionsFilter(),
+ new HttpExceptionFilter(),
+ );
+
+ // Global validation pipe
+ app.useGlobalPipes(
+ new ValidationPipe({
+ whitelist: true, // Strip properties that don't have decorators
+ forbidNonWhitelisted: true, // Throw error if non-whitelisted properties are present
+ transform: true, // Automatically transform payloads to DTO instances
+ transformOptions: {
+ enableImplicitConversion: true,
+ },
+ }),
+ );
+
+ const port = process.env.PORT || 3000;
+ await app.listen(port);
+
+ logger.log(`🚀 Application is running on: http://localhost:${port}/api/v1`);
+ logger.log(`📚 Environment: ${process.env.NODE_ENV || 'development'}`);
+ logger.log(`🔐 Auth0 Domain: ${process.env.AUTH0_DOMAIN || 'not configured'}`);
+}
+
+bootstrap();
diff --git a/backend/src/prisma/prisma.module.ts b/backend/src/prisma/prisma.module.ts
new file mode 100644
index 0000000..1dd44ed
--- /dev/null
+++ b/backend/src/prisma/prisma.module.ts
@@ -0,0 +1,9 @@
+import { Global, Module } from '@nestjs/common';
+import { PrismaService } from './prisma.service';
+
+@Global() // Makes PrismaService available everywhere without importing
+@Module({
+ providers: [PrismaService],
+ exports: [PrismaService],
+})
+export class PrismaModule {}
diff --git a/backend/src/prisma/prisma.service.ts b/backend/src/prisma/prisma.service.ts
new file mode 100644
index 0000000..f846734
--- /dev/null
+++ b/backend/src/prisma/prisma.service.ts
@@ -0,0 +1,51 @@
+import { Injectable, OnModuleInit, OnModuleDestroy, Logger } from '@nestjs/common';
+import { PrismaClient } from '@prisma/client';
+
+@Injectable()
+export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy {
+ private readonly logger = new Logger(PrismaService.name);
+
+ constructor() {
+ super({
+ log: process.env.NODE_ENV === 'development' ? ['query', 'error', 'warn'] : ['error'],
+ });
+ }
+
+ async onModuleInit() {
+ try {
+ await this.$connect();
+ this.logger.log('✅ Database connected successfully');
+ } catch (error) {
+ this.logger.error('❌ Database connection failed', error);
+ throw error;
+ }
+ }
+
+ async onModuleDestroy() {
+ await this.$disconnect();
+ this.logger.log('Database disconnected');
+ }
+
+ /**
+ * Clean database method for testing
+ * WARNING: Only use in development/testing!
+ */
+ async cleanDatabase() {
+ if (process.env.NODE_ENV === 'production') {
+ throw new Error('Cannot clean database in production!');
+ }
+
+ const models = Object.keys(this).filter(
+ (key) => !key.startsWith('_') && !key.startsWith('$'),
+ );
+
+ return Promise.all(
+ models.map((modelKey) => {
+ const model = this[modelKey as keyof this];
+ if (model && typeof model === 'object' && 'deleteMany' in model) {
+ return (model as any).deleteMany();
+ }
+ }),
+ );
+ }
+}
diff --git a/backend/src/routes/simpleAuth.ts b/backend/src/routes/simpleAuth.ts
deleted file mode 100644
index a947b21..0000000
--- a/backend/src/routes/simpleAuth.ts
+++ /dev/null
@@ -1,613 +0,0 @@
-import express, { Request, Response, NextFunction } from 'express';
-import {
- generateToken,
- verifyToken,
- getGoogleAuthUrl,
- exchangeCodeForTokens,
- getGoogleUserInfo,
- User
-} from '../config/simpleAuth';
-import databaseService from '../services/databaseService';
-
-const router = express.Router();
-
-// Enhanced logging for production debugging
-function logAuthEvent(event: string, details: any = {}) {
- const timestamp = new Date().toISOString();
- console.log(`🔐 [AUTH ${timestamp}] ${event}:`, JSON.stringify(details, null, 2));
-}
-
-// Validate environment variables on startup
-function validateAuthEnvironment() {
- const required = ['GOOGLE_CLIENT_ID', 'GOOGLE_CLIENT_SECRET', 'GOOGLE_REDIRECT_URI', 'FRONTEND_URL'];
- const missing = required.filter(key => !process.env[key]);
-
- if (missing.length > 0) {
- logAuthEvent('ENVIRONMENT_ERROR', { missing_variables: missing });
- return false;
- }
-
- // Validate URLs
- const frontendUrl = process.env.FRONTEND_URL;
- const redirectUri = process.env.GOOGLE_REDIRECT_URI;
-
- if (!frontendUrl?.startsWith('http')) {
- logAuthEvent('ENVIRONMENT_ERROR', { error: 'FRONTEND_URL must start with http/https' });
- return false;
- }
-
- if (!redirectUri?.startsWith('http')) {
- logAuthEvent('ENVIRONMENT_ERROR', { error: 'GOOGLE_REDIRECT_URI must start with http/https' });
- return false;
- }
-
- logAuthEvent('ENVIRONMENT_VALIDATED', {
- frontend_url: frontendUrl,
- redirect_uri: redirectUri,
- client_id_configured: !!process.env.GOOGLE_CLIENT_ID,
- client_secret_configured: !!process.env.GOOGLE_CLIENT_SECRET
- });
-
- return true;
-}
-
-// Validate environment on module load
-const isEnvironmentValid = validateAuthEnvironment();
-
-// Middleware to check authentication
-export function requireAuth(req: Request, res: Response, next: NextFunction) {
- try {
- const authHeader = req.headers.authorization;
-
- if (!authHeader || !authHeader.startsWith('Bearer ')) {
- logAuthEvent('AUTH_FAILED', {
- reason: 'no_token',
- ip: req.ip,
- path: req.path,
- headers_present: !!req.headers.authorization
- });
- return res.status(401).json({ error: 'No token provided' });
- }
-
- const token = authHeader.substring(7);
-
- if (!token || token.length < 10) {
- logAuthEvent('AUTH_FAILED', {
- reason: 'invalid_token_format',
- ip: req.ip,
- path: req.path,
- token_length: token?.length || 0
- });
- return res.status(401).json({ error: 'Invalid token format' });
- }
-
- const user = verifyToken(token);
-
- if (!user) {
- logAuthEvent('AUTH_FAILED', {
- reason: 'token_verification_failed',
- ip: req.ip,
- path: req.path,
- token_prefix: token.substring(0, 10) + '...'
- });
- return res.status(401).json({ error: 'Invalid or expired token' });
- }
-
- logAuthEvent('AUTH_SUCCESS', {
- user_id: user.id,
- user_email: user.email,
- user_role: user.role,
- ip: req.ip,
- path: req.path
- });
-
- (req as any).user = user;
- next();
- } catch (error) {
- logAuthEvent('AUTH_ERROR', {
- error: error instanceof Error ? error.message : 'Unknown error',
- ip: req.ip,
- path: req.path
- });
- return res.status(500).json({ error: 'Authentication system error' });
- }
-}
-
-// Middleware to check role
-export function requireRole(roles: string[]) {
- return (req: Request, res: Response, next: NextFunction) => {
- const user = (req as any).user;
-
- if (!user || !roles.includes(user.role)) {
- return res.status(403).json({ error: 'Insufficient permissions' });
- }
-
- next();
- };
-}
-
-// Get current user
-router.get('/me', requireAuth, (req: Request, res: Response) => {
- res.json((req as any).user);
-});
-
-// Setup status endpoint (required by frontend)
-router.get('/setup', async (req: Request, res: Response) => {
- try {
- const clientId = process.env.GOOGLE_CLIENT_ID;
- const clientSecret = process.env.GOOGLE_CLIENT_SECRET;
- const redirectUri = process.env.GOOGLE_REDIRECT_URI;
- const frontendUrl = process.env.FRONTEND_URL;
-
- logAuthEvent('SETUP_CHECK', {
- client_id_present: !!clientId,
- client_secret_present: !!clientSecret,
- redirect_uri_present: !!redirectUri,
- frontend_url_present: !!frontendUrl,
- environment_valid: isEnvironmentValid
- });
-
- // Check database connectivity
- let userCount = 0;
- let databaseConnected = false;
- try {
- userCount = await databaseService.getUserCount();
- databaseConnected = true;
- logAuthEvent('DATABASE_CHECK', { status: 'connected', user_count: userCount });
- } catch (dbError) {
- logAuthEvent('DATABASE_ERROR', {
- error: dbError instanceof Error ? dbError.message : 'Unknown database error'
- });
- return res.status(500).json({
- error: 'Database connection failed',
- details: 'Cannot connect to PostgreSQL database'
- });
- }
-
- const setupCompleted = !!(
- clientId &&
- clientSecret &&
- redirectUri &&
- frontendUrl &&
- clientId !== 'your-google-client-id-from-console' &&
- clientId !== 'your-google-client-id' &&
- isEnvironmentValid
- );
-
- const response = {
- setupCompleted,
- firstAdminCreated: userCount > 0,
- oauthConfigured: !!(clientId && clientSecret),
- databaseConnected,
- environmentValid: isEnvironmentValid,
- configuration: {
- google_oauth: !!(clientId && clientSecret),
- redirect_uri_configured: !!redirectUri,
- frontend_url_configured: !!frontendUrl,
- production_ready: setupCompleted && databaseConnected
- }
- };
-
- logAuthEvent('SETUP_STATUS', response);
- res.json(response);
-
- } catch (error) {
- logAuthEvent('SETUP_ERROR', {
- error: error instanceof Error ? error.message : 'Unknown setup error'
- });
- res.status(500).json({
- error: 'Setup check failed',
- details: error instanceof Error ? error.message : 'Unknown error'
- });
- }
-});
-
-// Start Google OAuth flow
-router.get('/google', (req: Request, res: Response) => {
- try {
- const authUrl = getGoogleAuthUrl();
- res.redirect(authUrl);
- } catch (error) {
- console.error('Error starting Google OAuth:', error);
- const frontendUrl = process.env.FRONTEND_URL || 'http://localhost:5173';
- res.redirect(`${frontendUrl}?error=oauth_not_configured`);
- }
-});
-
-// Handle Google OAuth callback (this is where Google redirects back to)
-router.get('/google/callback', async (req: Request, res: Response) => {
- const { code, error, state } = req.query;
- const frontendUrl = process.env.FRONTEND_URL || 'http://localhost:5173';
-
- logAuthEvent('OAUTH_CALLBACK', {
- has_code: !!code,
- has_error: !!error,
- error_type: error,
- state,
- frontend_url: frontendUrl,
- ip: req.ip,
- user_agent: req.get('User-Agent')
- });
-
- // Validate environment before proceeding
- if (!isEnvironmentValid) {
- logAuthEvent('OAUTH_CALLBACK_ERROR', { reason: 'invalid_environment' });
- return res.redirect(`${frontendUrl}?error=configuration_error&message=OAuth not properly configured`);
- }
-
- if (error) {
- logAuthEvent('OAUTH_ERROR', { error, ip: req.ip });
- return res.redirect(`${frontendUrl}?error=${error}&message=OAuth authorization failed`);
- }
-
- if (!code) {
- logAuthEvent('OAUTH_ERROR', { reason: 'no_authorization_code', ip: req.ip });
- return res.redirect(`${frontendUrl}?error=no_code&message=No authorization code received`);
- }
-
- try {
- logAuthEvent('OAUTH_TOKEN_EXCHANGE_START', { code_length: (code as string).length });
-
- // Exchange code for tokens
- const tokens = await exchangeCodeForTokens(code as string);
-
- if (!tokens || !tokens.access_token) {
- logAuthEvent('OAUTH_TOKEN_EXCHANGE_FAILED', { tokens_received: !!tokens });
- return res.redirect(`${frontendUrl}?error=token_exchange_failed&message=Failed to exchange authorization code`);
- }
-
- logAuthEvent('OAUTH_TOKEN_EXCHANGE_SUCCESS', { has_access_token: !!tokens.access_token });
-
- // Get user info
- const googleUser = await getGoogleUserInfo(tokens.access_token);
-
- if (!googleUser || !googleUser.email) {
- logAuthEvent('OAUTH_USER_INFO_FAILED', { user_data: !!googleUser });
- return res.redirect(`${frontendUrl}?error=user_info_failed&message=Failed to get user information from Google`);
- }
-
- logAuthEvent('OAUTH_USER_INFO_SUCCESS', {
- email: googleUser.email,
- name: googleUser.name,
- verified_email: googleUser.verified_email
- });
-
- // Check if user exists or create new user
- let user = await databaseService.getUserByEmail(googleUser.email);
-
- if (!user) {
- // Determine role - first user becomes admin, others need approval
- const approvedUserCount = await databaseService.getApprovedUserCount();
- const role = approvedUserCount === 0 ? 'administrator' : 'coordinator';
-
- logAuthEvent('USER_CREATION', {
- email: googleUser.email,
- role,
- is_first_user: approvedUserCount === 0
- });
-
- user = await databaseService.createUser({
- id: googleUser.id,
- google_id: googleUser.id,
- email: googleUser.email,
- name: googleUser.name,
- profile_picture_url: googleUser.picture,
- role
- });
-
- // Auto-approve first admin, others need approval
- if (approvedUserCount === 0) {
- await databaseService.updateUserApprovalStatus(googleUser.email, 'approved');
- user.approval_status = 'approved';
- logAuthEvent('FIRST_ADMIN_CREATED', { email: googleUser.email });
- } else {
- logAuthEvent('USER_PENDING_APPROVAL', { email: googleUser.email });
- }
- } else {
- // Update last sign in
- await databaseService.updateUserLastSignIn(googleUser.email);
- logAuthEvent('USER_LOGIN', {
- email: user.email,
- name: user.name,
- role: user.role,
- approval_status: user.approval_status
- });
- }
-
- // Check if user is approved
- if (user.approval_status !== 'approved') {
- logAuthEvent('USER_NOT_APPROVED', { email: user.email, status: user.approval_status });
- return res.redirect(`${frontendUrl}?error=pending_approval&message=Your account is pending administrator approval`);
- }
-
- // Generate JWT token
- const token = generateToken(user);
-
- logAuthEvent('JWT_TOKEN_GENERATED', {
- user_id: user.id,
- email: user.email,
- role: user.role,
- token_length: token.length
- });
-
- // Redirect to frontend with token
- const callbackUrl = `${frontendUrl}/auth/callback?token=${token}`;
- logAuthEvent('OAUTH_SUCCESS_REDIRECT', { callback_url: callbackUrl });
- res.redirect(callbackUrl);
-
- } catch (error) {
- logAuthEvent('OAUTH_CALLBACK_ERROR', {
- error: error instanceof Error ? error.message : 'Unknown error',
- stack: error instanceof Error ? error.stack : undefined,
- ip: req.ip
- });
- res.redirect(`${frontendUrl}?error=oauth_failed&message=Authentication failed due to server error`);
- }
-});
-
-// Exchange OAuth code for JWT token (alternative endpoint for frontend)
-router.post('/google/exchange', async (req: Request, res: Response) => {
- const { code } = req.body;
-
- if (!code) {
- return res.status(400).json({ error: 'Authorization code is required' });
- }
-
- try {
- // Exchange code for tokens
- const tokens = await exchangeCodeForTokens(code);
-
- // Get user info
- const googleUser = await getGoogleUserInfo(tokens.access_token);
-
- // Check if user exists or create new user
- let user = await databaseService.getUserByEmail(googleUser.email);
-
- if (!user) {
- // Determine role - first user becomes admin
- const userCount = await databaseService.getUserCount();
- const role = userCount === 0 ? 'administrator' : 'coordinator';
-
- user = await databaseService.createUser({
- id: googleUser.id,
- google_id: googleUser.id,
- email: googleUser.email,
- name: googleUser.name,
- profile_picture_url: googleUser.picture,
- role
- });
- } else {
- // Update last sign in
- await databaseService.updateUserLastSignIn(googleUser.email);
- console.log(`✅ User logged in: ${user.name} (${user.email})`);
- }
-
- // Generate JWT token
- const token = generateToken(user);
-
- // Return token to frontend
- res.json({
- token,
- user: {
- id: user.id,
- email: user.email,
- name: user.name,
- picture: user.profile_picture_url,
- role: user.role
- }
- });
-
- } catch (error) {
- console.error('Error in OAuth exchange:', error);
- res.status(500).json({ error: 'Failed to exchange authorization code' });
- }
-});
-
-// Get OAuth URL for frontend to redirect to
-router.get('/google/url', (req: Request, res: Response) => {
- try {
- const authUrl = getGoogleAuthUrl();
- res.json({ url: authUrl });
- } catch (error) {
- console.error('Error getting Google OAuth URL:', error);
- res.status(500).json({ error: 'OAuth not configured' });
- }
-});
-
-// Logout
-router.post('/logout', (req: Request, res: Response) => {
- // With JWT, logout is handled client-side by removing the token
- res.json({ message: 'Logged out successfully' });
-});
-
-// Get auth status
-router.get('/status', (req: Request, res: Response) => {
- const authHeader = req.headers.authorization;
-
- if (!authHeader || !authHeader.startsWith('Bearer ')) {
- return res.json({ authenticated: false });
- }
-
- const token = authHeader.substring(7);
- const user = verifyToken(token);
-
- if (!user) {
- return res.json({ authenticated: false });
- }
-
- res.json({
- authenticated: true,
- user: {
- id: user.id,
- email: user.email,
- name: user.name,
- picture: user.profile_picture_url,
- role: user.role
- }
- });
-});
-
-// USER MANAGEMENT ENDPOINTS
-
-// List all users (admin only)
-router.get('/users', requireAuth, requireRole(['administrator']), async (req: Request, res: Response) => {
- try {
- const users = await databaseService.getAllUsers();
-
- const userList = users.map(user => ({
- id: user.id,
- email: user.email,
- name: user.name,
- picture: user.profile_picture_url,
- role: user.role,
- created_at: user.created_at,
- last_login: user.last_login,
- provider: 'google'
- }));
-
- res.json(userList);
- } catch (error) {
- console.error('Error fetching users:', error);
- res.status(500).json({ error: 'Failed to fetch users' });
- }
-});
-
-// Update user role (admin only)
-router.patch('/users/:email/role', requireAuth, requireRole(['administrator']), async (req: Request, res: Response) => {
- const { email } = req.params;
- const { role } = req.body;
-
- if (!['administrator', 'coordinator', 'driver'].includes(role)) {
- return res.status(400).json({ error: 'Invalid role' });
- }
-
- try {
- const user = await databaseService.updateUserRole(email, role);
- if (!user) {
- return res.status(404).json({ error: 'User not found' });
- }
-
- res.json({
- success: true,
- user: {
- id: user.id,
- email: user.email,
- name: user.name,
- role: user.role
- }
- });
- } catch (error) {
- console.error('Error updating user role:', error);
- res.status(500).json({ error: 'Failed to update user role' });
- }
-});
-
-// Delete user (admin only)
-router.delete('/users/:email', requireAuth, requireRole(['administrator']), async (req: Request, res: Response) => {
- const { email } = req.params;
- const currentUser = (req as any).user;
-
- // Prevent admin from deleting themselves
- if (email === currentUser.email) {
- return res.status(400).json({ error: 'Cannot delete your own account' });
- }
-
- try {
- const deletedUser = await databaseService.deleteUser(email);
-
- if (!deletedUser) {
- return res.status(404).json({ error: 'User not found' });
- }
-
- res.json({ success: true, message: 'User deleted successfully' });
- } catch (error) {
- console.error('Error deleting user:', error);
- res.status(500).json({ error: 'Failed to delete user' });
- }
-});
-
-// Get user by email (admin only)
-router.get('/users/:email', requireAuth, requireRole(['administrator']), async (req: Request, res: Response) => {
- const { email } = req.params;
-
- try {
- const user = await databaseService.getUserByEmail(email);
- if (!user) {
- return res.status(404).json({ error: 'User not found' });
- }
-
- res.json({
- id: user.id,
- email: user.email,
- name: user.name,
- picture: user.profile_picture_url,
- role: user.role,
- created_at: user.created_at,
- last_login: user.last_login,
- provider: 'google',
- approval_status: user.approval_status
- });
- } catch (error) {
- console.error('Error fetching user:', error);
- res.status(500).json({ error: 'Failed to fetch user' });
- }
-});
-
-// USER APPROVAL ENDPOINTS
-
-// Get pending users (admin only)
-router.get('/users/pending/list', requireAuth, requireRole(['administrator']), async (req: Request, res: Response) => {
- try {
- const pendingUsers = await databaseService.getPendingUsers();
-
- const userList = pendingUsers.map(user => ({
- id: user.id,
- email: user.email,
- name: user.name,
- picture: user.profile_picture_url,
- role: user.role,
- created_at: user.created_at,
- provider: 'google',
- approval_status: user.approval_status
- }));
-
- res.json(userList);
- } catch (error) {
- console.error('Error fetching pending users:', error);
- res.status(500).json({ error: 'Failed to fetch pending users' });
- }
-});
-
-// Approve or deny user (admin only)
-router.patch('/users/:email/approval', requireAuth, requireRole(['administrator']), async (req: Request, res: Response) => {
- const { email } = req.params;
- const { status } = req.body;
-
- if (!['approved', 'denied'].includes(status)) {
- return res.status(400).json({ error: 'Invalid approval status. Must be "approved" or "denied"' });
- }
-
- try {
- const user = await databaseService.updateUserApprovalStatus(email, status);
- if (!user) {
- return res.status(404).json({ error: 'User not found' });
- }
-
- res.json({
- success: true,
- message: `User ${status} successfully`,
- user: {
- id: user.id,
- email: user.email,
- name: user.name,
- role: user.role,
- approval_status: user.approval_status
- }
- });
- } catch (error) {
- console.error('Error updating user approval:', error);
- res.status(500).json({ error: 'Failed to update user approval' });
- }
-});
-
-export default router;
diff --git a/backend/src/services/authService.ts b/backend/src/services/authService.ts
deleted file mode 100644
index 1968c6f..0000000
--- a/backend/src/services/authService.ts
+++ /dev/null
@@ -1,197 +0,0 @@
-const jwt = require('jsonwebtoken');
-import { Request, Response, NextFunction } from 'express';
-import { OAuth2Client } from 'google-auth-library';
-import dataService from './unifiedDataService';
-
-// Simplified authentication service - removes excessive logging and complexity
-class AuthService {
- private jwtSecret: string;
- private jwtExpiry: string = '24h';
- private googleClient: OAuth2Client;
-
- constructor() {
- // Auto-generate a secure JWT secret if not provided
- if (process.env.JWT_SECRET) {
- this.jwtSecret = process.env.JWT_SECRET;
- console.log('Using JWT_SECRET from environment');
- } else {
- // Generate a cryptographically secure random secret
- const crypto = require('crypto');
- this.jwtSecret = crypto.randomBytes(64).toString('hex');
- console.log('Generated new JWT_SECRET (this will change on restart)');
- console.log('To persist sessions across restarts, set JWT_SECRET in .env');
- }
-
- // Initialize Google OAuth client
- this.googleClient = new OAuth2Client(process.env.GOOGLE_CLIENT_ID);
- }
-
- // Generate JWT token
- generateToken(user: any): string {
- const payload = { id: user.id, email: user.email, role: user.role };
- return jwt.sign(payload, this.jwtSecret, { expiresIn: this.jwtExpiry }) as string;
- }
-
- // Verify Google ID token from frontend
- async verifyGoogleToken(credential: string): Promise<{ user: any; token: string }> {
- try {
- // Verify the token with Google
- const ticket = await this.googleClient.verifyIdToken({
- idToken: credential,
- audience: process.env.GOOGLE_CLIENT_ID,
- });
-
- const payload = ticket.getPayload();
- if (!payload || !payload.email) {
- throw new Error('Invalid token payload');
- }
-
- // Find or create user
- let user = await dataService.getUserByEmail(payload.email);
-
- if (!user) {
- // Auto-create user with coordinator role
- user = await dataService.createUser({
- email: payload.email,
- name: payload.name || payload.email,
- role: 'coordinator',
- googleId: payload.sub
- });
- }
-
- // Generate our JWT
- const token = this.generateToken(user);
-
- return { user, token };
- } catch (error) {
- console.error('Token verification error:', error);
- throw new Error('Failed to verify Google token');
- }
- }
-
- // Verify JWT token
- verifyToken(token: string): any {
- try {
- return jwt.verify(token, this.jwtSecret);
- } catch (error) {
- return null;
- }
- }
-
- // Middleware to check authentication
- requireAuth = async (req: Request & { user?: any }, res: Response, next: NextFunction) => {
- const token = req.headers.authorization?.replace('Bearer ', '');
-
- if (!token) {
- return res.status(401).json({ error: 'Authentication required' });
- }
-
- const decoded = this.verifyToken(token);
- if (!decoded) {
- return res.status(401).json({ error: 'Invalid or expired token' });
- }
-
- // Get fresh user data
- const user = await dataService.getUserById(decoded.id);
- if (!user) {
- return res.status(401).json({ error: 'User not found' });
- }
-
- req.user = user;
- next();
- };
-
- // Middleware to check role
- requireRole = (roles: string[]) => {
- return (req: Request & { user?: any }, res: Response, next: NextFunction) => {
- if (!req.user) {
- return res.status(401).json({ error: 'Authentication required' });
- }
-
- if (!roles.includes(req.user.role)) {
- return res.status(403).json({ error: 'Insufficient permissions' });
- }
-
- next();
- };
- };
-
- // Google OAuth helpers
- getGoogleAuthUrl(): string {
- if (!process.env.GOOGLE_CLIENT_ID || !process.env.GOOGLE_REDIRECT_URI) {
- throw new Error('Google OAuth not configured. Please set GOOGLE_CLIENT_ID and GOOGLE_REDIRECT_URI in .env file');
- }
-
- const params = new URLSearchParams({
- client_id: process.env.GOOGLE_CLIENT_ID,
- redirect_uri: process.env.GOOGLE_REDIRECT_URI,
- response_type: 'code',
- scope: 'email profile',
- access_type: 'offline',
- prompt: 'consent'
- });
-
- return `https://accounts.google.com/o/oauth2/v2/auth?${params}`;
- }
-
- async exchangeGoogleCode(code: string): Promise {
- const response = await fetch('https://oauth2.googleapis.com/token', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({
- code,
- client_id: process.env.GOOGLE_CLIENT_ID,
- client_secret: process.env.GOOGLE_CLIENT_SECRET,
- redirect_uri: process.env.GOOGLE_REDIRECT_URI,
- grant_type: 'authorization_code'
- })
- });
-
- if (!response.ok) {
- throw new Error('Failed to exchange authorization code');
- }
-
- return response.json();
- }
-
- async getGoogleUserInfo(accessToken: string): Promise {
- const response = await fetch('https://www.googleapis.com/oauth2/v2/userinfo', {
- headers: { Authorization: `Bearer ${accessToken}` }
- });
-
- if (!response.ok) {
- throw new Error('Failed to get user info');
- }
-
- return response.json();
- }
-
- // Simplified login/signup
- async handleGoogleAuth(code: string): Promise<{ user: any; token: string }> {
- // Exchange code for tokens
- const tokens = await this.exchangeGoogleCode(code);
-
- // Get user info
- const googleUser = await this.getGoogleUserInfo(tokens.access_token);
-
- // Find or create user
- let user = await dataService.getUserByEmail(googleUser.email);
-
- if (!user) {
- // Auto-create user with coordinator role
- user = await dataService.createUser({
- email: googleUser.email,
- name: googleUser.name,
- role: 'coordinator',
- googleId: googleUser.id
- });
- }
-
- // Generate JWT
- const token = this.generateToken(user);
-
- return { user, token };
- }
-}
-
-export default new AuthService();
\ No newline at end of file
diff --git a/backend/src/services/jwtKeyManager.ts b/backend/src/services/jwtKeyManager.ts
deleted file mode 100644
index 1209a90..0000000
--- a/backend/src/services/jwtKeyManager.ts
+++ /dev/null
@@ -1,183 +0,0 @@
-import crypto from 'crypto';
-import jwt from 'jsonwebtoken';
-
-export interface User {
- id: string;
- google_id: string;
- email: string;
- name: string;
- profile_picture_url?: string;
- role: 'driver' | 'coordinator' | 'administrator';
- created_at?: string;
- last_login?: string;
- is_active?: boolean;
- updated_at?: string;
-}
-
-class JWTKeyManager {
- private currentSecret: string;
- private previousSecret: string | null = null;
- private rotationInterval: NodeJS.Timeout | null = null;
- private gracePeriodTimeout: NodeJS.Timeout | null = null;
-
- constructor() {
- console.log('🔑 Initializing JWT Key Manager with automatic rotation');
- this.currentSecret = this.generateSecret();
- this.startRotation();
- }
-
- private generateSecret(): string {
- const secret = crypto.randomBytes(64).toString('hex');
- console.log('🔄 Generated new JWT signing key (length:', secret.length, 'chars)');
- return secret;
- }
-
- private startRotation() {
- // Rotate every 24 hours (86400000 ms)
- this.rotationInterval = setInterval(() => {
- this.rotateKey();
- }, 24 * 60 * 60 * 1000);
-
- console.log('⏰ JWT key rotation scheduled every 24 hours');
-
- // Also rotate on startup after 1 hour to test the system
- setTimeout(() => {
- console.log('🧪 Performing initial key rotation test...');
- this.rotateKey();
- }, 60 * 60 * 1000); // 1 hour
- }
-
- private rotateKey() {
- console.log('🔄 Rotating JWT signing key...');
-
- // Store current secret as previous
- this.previousSecret = this.currentSecret;
-
- // Generate new current secret
- this.currentSecret = this.generateSecret();
-
- console.log('✅ JWT key rotation completed. Grace period: 24 hours');
-
- // Clear any existing grace period timeout
- if (this.gracePeriodTimeout) {
- clearTimeout(this.gracePeriodTimeout);
- }
-
- // Clean up previous secret after 24 hours (grace period)
- this.gracePeriodTimeout = setTimeout(() => {
- this.previousSecret = null;
- console.log('🧹 Grace period ended. Previous JWT key cleaned up');
- }, 24 * 60 * 60 * 1000);
- }
-
- generateToken(user: User): string {
- const payload = {
- id: user.id,
- google_id: user.google_id,
- email: user.email,
- name: user.name,
- profile_picture_url: user.profile_picture_url,
- role: user.role,
- iat: Math.floor(Date.now() / 1000) // Issued at time
- };
-
- return jwt.sign(payload, this.currentSecret, {
- expiresIn: '24h',
- issuer: 'vip-coordinator',
- audience: 'vip-coordinator-users'
- });
- }
-
- verifyToken(token: string): User | null {
- try {
- // Try current secret first
- const decoded = jwt.verify(token, this.currentSecret, {
- issuer: 'vip-coordinator',
- audience: 'vip-coordinator-users'
- }) as any;
-
- return {
- id: decoded.id,
- google_id: decoded.google_id,
- email: decoded.email,
- name: decoded.name,
- profile_picture_url: decoded.profile_picture_url,
- role: decoded.role
- };
- } catch (error) {
- // Try previous secret during grace period
- if (this.previousSecret) {
- try {
- const decoded = jwt.verify(token, this.previousSecret, {
- issuer: 'vip-coordinator',
- audience: 'vip-coordinator-users'
- }) as any;
-
- console.log('🔄 Token verified using previous key (grace period)');
-
- return {
- id: decoded.id,
- google_id: decoded.google_id,
- email: decoded.email,
- name: decoded.name,
- profile_picture_url: decoded.profile_picture_url,
- role: decoded.role
- };
- } catch (gracePeriodError) {
- console.log('❌ Token verification failed with both current and previous keys');
- return null;
- }
- }
-
- console.log('❌ Token verification failed:', error instanceof Error ? error.message : 'Unknown error');
- return null;
- }
- }
-
- // Get status for monitoring/debugging
- getStatus() {
- return {
- hasCurrentKey: !!this.currentSecret,
- hasPreviousKey: !!this.previousSecret,
- rotationActive: !!this.rotationInterval,
- gracePeriodActive: !!this.gracePeriodTimeout
- };
- }
-
- // Cleanup on shutdown
- destroy() {
- console.log('🛑 Shutting down JWT Key Manager...');
-
- if (this.rotationInterval) {
- clearInterval(this.rotationInterval);
- this.rotationInterval = null;
- }
-
- if (this.gracePeriodTimeout) {
- clearTimeout(this.gracePeriodTimeout);
- this.gracePeriodTimeout = null;
- }
-
- console.log('✅ JWT Key Manager shutdown complete');
- }
-
- // Manual rotation for testing/emergency
- forceRotation() {
- console.log('🚨 Manual key rotation triggered');
- this.rotateKey();
- }
-}
-
-// Singleton instance
-export const jwtKeyManager = new JWTKeyManager();
-
-// Graceful shutdown handling
-process.on('SIGTERM', () => {
- jwtKeyManager.destroy();
-});
-
-process.on('SIGINT', () => {
- jwtKeyManager.destroy();
-});
-
-export default jwtKeyManager;
\ No newline at end of file
diff --git a/backend/src/users/dto/approve-user.dto.ts b/backend/src/users/dto/approve-user.dto.ts
new file mode 100644
index 0000000..fdaf083
--- /dev/null
+++ b/backend/src/users/dto/approve-user.dto.ts
@@ -0,0 +1,6 @@
+import { IsBoolean } from 'class-validator';
+
+export class ApproveUserDto {
+ @IsBoolean()
+ isApproved: boolean;
+}
diff --git a/backend/src/users/dto/index.ts b/backend/src/users/dto/index.ts
new file mode 100644
index 0000000..a29a5eb
--- /dev/null
+++ b/backend/src/users/dto/index.ts
@@ -0,0 +1,2 @@
+export * from './update-user.dto';
+export * from './approve-user.dto';
diff --git a/backend/src/users/dto/update-user.dto.ts b/backend/src/users/dto/update-user.dto.ts
new file mode 100644
index 0000000..e27018a
--- /dev/null
+++ b/backend/src/users/dto/update-user.dto.ts
@@ -0,0 +1,12 @@
+import { IsString, IsEnum, IsOptional } from 'class-validator';
+import { Role } from '@prisma/client';
+
+export class UpdateUserDto {
+ @IsString()
+ @IsOptional()
+ name?: string;
+
+ @IsEnum(Role)
+ @IsOptional()
+ role?: Role;
+}
diff --git a/backend/src/users/users.controller.ts b/backend/src/users/users.controller.ts
new file mode 100644
index 0000000..dd1bf39
--- /dev/null
+++ b/backend/src/users/users.controller.ts
@@ -0,0 +1,57 @@
+import {
+ Controller,
+ Get,
+ Patch,
+ Delete,
+ Body,
+ Param,
+ UseGuards,
+} from '@nestjs/common';
+import { UsersService } from './users.service';
+import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
+import { AbilitiesGuard } from '../auth/guards/abilities.guard';
+import { CanRead, CanUpdate, CanDelete, CheckAbilities } from '../auth/decorators/check-ability.decorator';
+import { Action } from '../auth/abilities/ability.factory';
+import { UpdateUserDto, ApproveUserDto } from './dto';
+
+@Controller('users')
+@UseGuards(JwtAuthGuard, AbilitiesGuard)
+export class UsersController {
+ constructor(private readonly usersService: UsersService) {}
+
+ @Get()
+ @CanRead('User')
+ findAll() {
+ return this.usersService.findAll();
+ }
+
+ @Get('pending')
+ @CanRead('User')
+ getPendingUsers() {
+ return this.usersService.getPendingUsers();
+ }
+
+ @Get(':id')
+ @CanRead('User')
+ findOne(@Param('id') id: string) {
+ return this.usersService.findOne(id);
+ }
+
+ @Patch(':id')
+ @CanUpdate('User')
+ update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) {
+ return this.usersService.update(id, updateUserDto);
+ }
+
+ @Patch(':id/approve')
+ @CheckAbilities({ action: Action.Approve, subject: 'User' })
+ approve(@Param('id') id: string, @Body() approveUserDto: ApproveUserDto) {
+ return this.usersService.approve(id, approveUserDto);
+ }
+
+ @Delete(':id')
+ @CanDelete('User')
+ remove(@Param('id') id: string) {
+ return this.usersService.remove(id);
+ }
+}
diff --git a/backend/src/users/users.module.ts b/backend/src/users/users.module.ts
new file mode 100644
index 0000000..513776d
--- /dev/null
+++ b/backend/src/users/users.module.ts
@@ -0,0 +1,10 @@
+import { Module } from '@nestjs/common';
+import { UsersController } from './users.controller';
+import { UsersService } from './users.service';
+
+@Module({
+ controllers: [UsersController],
+ providers: [UsersService],
+ exports: [UsersService],
+})
+export class UsersModule {}
diff --git a/backend/src/users/users.service.ts b/backend/src/users/users.service.ts
new file mode 100644
index 0000000..d797852
--- /dev/null
+++ b/backend/src/users/users.service.ts
@@ -0,0 +1,106 @@
+import { Injectable, NotFoundException, Logger } from '@nestjs/common';
+import { PrismaService } from '../prisma/prisma.service';
+import { UpdateUserDto, ApproveUserDto } from './dto';
+import { Role } from '@prisma/client';
+
+@Injectable()
+export class UsersService {
+ private readonly logger = new Logger(UsersService.name);
+
+ constructor(private prisma: PrismaService) {}
+
+ async findAll() {
+ return this.prisma.user.findMany({
+ where: { deletedAt: null },
+ include: { driver: true },
+ orderBy: { createdAt: 'desc' },
+ });
+ }
+
+ async findOne(id: string) {
+ const user = await this.prisma.user.findFirst({
+ where: { id, deletedAt: null },
+ include: { driver: true },
+ });
+
+ if (!user) {
+ throw new NotFoundException(`User with ID ${id} not found`);
+ }
+
+ return user;
+ }
+
+ async update(id: string, updateUserDto: UpdateUserDto) {
+ const user = await this.findOne(id);
+
+ this.logger.log(`Updating user ${id}: ${JSON.stringify(updateUserDto)}`);
+
+ // Handle role change and Driver record synchronization
+ if (updateUserDto.role && updateUserDto.role !== user.role) {
+ // If changing TO DRIVER role, create a Driver record if one doesn't exist
+ if (updateUserDto.role === Role.DRIVER && !user.driver) {
+ this.logger.log(
+ `Creating Driver record for user ${user.email} (role change to DRIVER)`,
+ );
+ await this.prisma.driver.create({
+ data: {
+ name: user.name || user.email,
+ phone: user.email, // Use email as placeholder for phone
+ userId: user.id,
+ },
+ });
+ }
+
+ // If changing FROM DRIVER role to something else, remove the Driver record
+ if (user.role === Role.DRIVER && updateUserDto.role !== Role.DRIVER && user.driver) {
+ this.logger.log(
+ `Removing Driver record for user ${user.email} (role change from DRIVER to ${updateUserDto.role})`,
+ );
+ await this.prisma.driver.delete({
+ where: { id: user.driver.id },
+ });
+ }
+ }
+
+ return this.prisma.user.update({
+ where: { id: user.id },
+ data: updateUserDto,
+ include: { driver: true },
+ });
+ }
+
+ async approve(id: string, approveUserDto: ApproveUserDto) {
+ const user = await this.findOne(id);
+
+ this.logger.log(
+ `${approveUserDto.isApproved ? 'Approving' : 'Denying'} user: ${user.email}`,
+ );
+
+ return this.prisma.user.update({
+ where: { id: user.id },
+ data: { isApproved: approveUserDto.isApproved },
+ include: { driver: true },
+ });
+ }
+
+ async remove(id: string) {
+ const user = await this.findOne(id);
+
+ this.logger.log(`Soft deleting user: ${user.email}`);
+
+ return this.prisma.user.update({
+ where: { id: user.id },
+ data: { deletedAt: new Date() },
+ });
+ }
+
+ async getPendingUsers() {
+ return this.prisma.user.findMany({
+ where: {
+ deletedAt: null,
+ isApproved: false,
+ },
+ orderBy: { createdAt: 'asc' },
+ });
+ }
+}
diff --git a/backend/src/vehicles/dto/create-vehicle.dto.ts b/backend/src/vehicles/dto/create-vehicle.dto.ts
new file mode 100644
index 0000000..fa85468
--- /dev/null
+++ b/backend/src/vehicles/dto/create-vehicle.dto.ts
@@ -0,0 +1,30 @@
+import { IsString, IsEnum, IsInt, IsOptional, Min } from 'class-validator';
+import { VehicleType, VehicleStatus } from '@prisma/client';
+
+export class CreateVehicleDto {
+ @IsString()
+ name: string;
+
+ @IsEnum(VehicleType)
+ type: VehicleType;
+
+ @IsString()
+ @IsOptional()
+ licensePlate?: string;
+
+ @IsInt()
+ @Min(1)
+ seatCapacity: number;
+
+ @IsEnum(VehicleStatus)
+ @IsOptional()
+ status?: VehicleStatus;
+
+ @IsString()
+ @IsOptional()
+ currentDriverId?: string;
+
+ @IsString()
+ @IsOptional()
+ notes?: string;
+}
diff --git a/backend/src/vehicles/dto/index.ts b/backend/src/vehicles/dto/index.ts
new file mode 100644
index 0000000..d6d4aec
--- /dev/null
+++ b/backend/src/vehicles/dto/index.ts
@@ -0,0 +1,2 @@
+export * from './create-vehicle.dto';
+export * from './update-vehicle.dto';
diff --git a/backend/src/vehicles/dto/update-vehicle.dto.ts b/backend/src/vehicles/dto/update-vehicle.dto.ts
new file mode 100644
index 0000000..953917b
--- /dev/null
+++ b/backend/src/vehicles/dto/update-vehicle.dto.ts
@@ -0,0 +1,4 @@
+import { PartialType } from '@nestjs/mapped-types';
+import { CreateVehicleDto } from './create-vehicle.dto';
+
+export class UpdateVehicleDto extends PartialType(CreateVehicleDto) {}
diff --git a/backend/src/vehicles/vehicles.controller.ts b/backend/src/vehicles/vehicles.controller.ts
new file mode 100644
index 0000000..ba5632f
--- /dev/null
+++ b/backend/src/vehicles/vehicles.controller.ts
@@ -0,0 +1,63 @@
+import {
+ Controller,
+ Get,
+ Post,
+ Patch,
+ Delete,
+ Body,
+ Param,
+ Query,
+ UseGuards,
+} from '@nestjs/common';
+import { VehiclesService } from './vehicles.service';
+import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
+import { RolesGuard } from '../auth/guards/roles.guard';
+import { Roles } from '../auth/decorators/roles.decorator';
+import { Role } from '@prisma/client';
+import { CreateVehicleDto, UpdateVehicleDto } from './dto';
+
+@Controller('vehicles')
+@UseGuards(JwtAuthGuard, RolesGuard)
+export class VehiclesController {
+ constructor(private readonly vehiclesService: VehiclesService) {}
+
+ @Post()
+ @Roles(Role.ADMINISTRATOR, Role.COORDINATOR)
+ create(@Body() createVehicleDto: CreateVehicleDto) {
+ return this.vehiclesService.create(createVehicleDto);
+ }
+
+ @Get()
+ findAll() {
+ return this.vehiclesService.findAll();
+ }
+
+ @Get('available')
+ findAvailable() {
+ return this.vehiclesService.findAvailable();
+ }
+
+ @Get('utilization')
+ @Roles(Role.ADMINISTRATOR, Role.COORDINATOR)
+ getUtilization() {
+ return this.vehiclesService.getUtilization();
+ }
+
+ @Get(':id')
+ findOne(@Param('id') id: string) {
+ return this.vehiclesService.findOne(id);
+ }
+
+ @Patch(':id')
+ @Roles(Role.ADMINISTRATOR, Role.COORDINATOR)
+ update(@Param('id') id: string, @Body() updateVehicleDto: UpdateVehicleDto) {
+ return this.vehiclesService.update(id, updateVehicleDto);
+ }
+
+ @Delete(':id')
+ @Roles(Role.ADMINISTRATOR, Role.COORDINATOR)
+ remove(@Param('id') id: string, @Query('hard') hard?: string) {
+ const isHardDelete = hard === 'true';
+ return this.vehiclesService.remove(id, isHardDelete);
+ }
+}
diff --git a/backend/src/vehicles/vehicles.module.ts b/backend/src/vehicles/vehicles.module.ts
new file mode 100644
index 0000000..395336a
--- /dev/null
+++ b/backend/src/vehicles/vehicles.module.ts
@@ -0,0 +1,12 @@
+import { Module } from '@nestjs/common';
+import { VehiclesService } from './vehicles.service';
+import { VehiclesController } from './vehicles.controller';
+import { PrismaModule } from '../prisma/prisma.module';
+
+@Module({
+ imports: [PrismaModule],
+ controllers: [VehiclesController],
+ providers: [VehiclesService],
+ exports: [VehiclesService],
+})
+export class VehiclesModule {}
diff --git a/backend/src/vehicles/vehicles.service.ts b/backend/src/vehicles/vehicles.service.ts
new file mode 100644
index 0000000..757d4b4
--- /dev/null
+++ b/backend/src/vehicles/vehicles.service.ts
@@ -0,0 +1,140 @@
+import { Injectable, NotFoundException, Logger } from '@nestjs/common';
+import { PrismaService } from '../prisma/prisma.service';
+import { CreateVehicleDto, UpdateVehicleDto } from './dto';
+
+@Injectable()
+export class VehiclesService {
+ private readonly logger = new Logger(VehiclesService.name);
+
+ constructor(private prisma: PrismaService) {}
+
+ async create(createVehicleDto: CreateVehicleDto) {
+ this.logger.log(`Creating vehicle: ${createVehicleDto.name}`);
+
+ return this.prisma.vehicle.create({
+ data: createVehicleDto,
+ include: {
+ currentDriver: true,
+ events: {
+ where: { deletedAt: null },
+ include: { vip: true },
+ },
+ },
+ });
+ }
+
+ async findAll() {
+ return this.prisma.vehicle.findMany({
+ where: { deletedAt: null },
+ include: {
+ currentDriver: true,
+ events: {
+ where: { deletedAt: null },
+ include: { vip: true, driver: true },
+ orderBy: { startTime: 'asc' },
+ },
+ },
+ orderBy: { name: 'asc' },
+ });
+ }
+
+ async findAvailable() {
+ return this.prisma.vehicle.findMany({
+ where: {
+ deletedAt: null,
+ status: 'AVAILABLE',
+ },
+ include: {
+ currentDriver: true,
+ },
+ orderBy: { name: 'asc' },
+ });
+ }
+
+ async findOne(id: string) {
+ const vehicle = await this.prisma.vehicle.findFirst({
+ where: { id, deletedAt: null },
+ include: {
+ currentDriver: true,
+ events: {
+ where: { deletedAt: null },
+ include: { vip: true, driver: true },
+ orderBy: { startTime: 'asc' },
+ },
+ },
+ });
+
+ if (!vehicle) {
+ throw new NotFoundException(`Vehicle with ID ${id} not found`);
+ }
+
+ return vehicle;
+ }
+
+ async update(id: string, updateVehicleDto: UpdateVehicleDto) {
+ const vehicle = await this.findOne(id);
+
+ this.logger.log(`Updating vehicle ${id}: ${vehicle.name}`);
+
+ return this.prisma.vehicle.update({
+ where: { id: vehicle.id },
+ data: updateVehicleDto,
+ include: {
+ currentDriver: true,
+ events: {
+ where: { deletedAt: null },
+ include: { vip: true, driver: true },
+ },
+ },
+ });
+ }
+
+ async remove(id: string, hardDelete = false) {
+ const vehicle = await this.findOne(id);
+
+ if (hardDelete) {
+ this.logger.log(`Hard deleting vehicle: ${vehicle.name}`);
+ return this.prisma.vehicle.delete({
+ where: { id: vehicle.id },
+ });
+ }
+
+ this.logger.log(`Soft deleting vehicle: ${vehicle.name}`);
+ return this.prisma.vehicle.update({
+ where: { id: vehicle.id },
+ data: { deletedAt: new Date() },
+ });
+ }
+
+ /**
+ * Get vehicle utilization statistics
+ */
+ async getUtilization() {
+ const vehicles = await this.findAll();
+
+ const stats = vehicles.map((vehicle) => {
+ const upcomingEvents = vehicle.events.filter(
+ (event) => new Date(event.startTime) > new Date(),
+ );
+
+ return {
+ id: vehicle.id,
+ name: vehicle.name,
+ type: vehicle.type,
+ seatCapacity: vehicle.seatCapacity,
+ status: vehicle.status,
+ upcomingTrips: upcomingEvents.length,
+ currentDriver: vehicle.currentDriver?.name,
+ };
+ });
+
+ return {
+ totalVehicles: vehicles.length,
+ available: vehicles.filter((v) => v.status === 'AVAILABLE').length,
+ inUse: vehicles.filter((v) => v.status === 'IN_USE').length,
+ maintenance: vehicles.filter((v) => v.status === 'MAINTENANCE').length,
+ reserved: vehicles.filter((v) => v.status === 'RESERVED').length,
+ vehicles: stats,
+ };
+ }
+}
diff --git a/backend/src/vips/dto/create-vip.dto.ts b/backend/src/vips/dto/create-vip.dto.ts
new file mode 100644
index 0000000..8034ce2
--- /dev/null
+++ b/backend/src/vips/dto/create-vip.dto.ts
@@ -0,0 +1,39 @@
+import {
+ IsString,
+ IsEnum,
+ IsOptional,
+ IsBoolean,
+ IsDateString,
+} from 'class-validator';
+import { Department, ArrivalMode } from '@prisma/client';
+
+export class CreateVipDto {
+ @IsString()
+ name: string;
+
+ @IsString()
+ @IsOptional()
+ organization?: string;
+
+ @IsEnum(Department)
+ department: Department;
+
+ @IsEnum(ArrivalMode)
+ arrivalMode: ArrivalMode;
+
+ @IsDateString()
+ @IsOptional()
+ expectedArrival?: string;
+
+ @IsBoolean()
+ @IsOptional()
+ airportPickup?: boolean;
+
+ @IsBoolean()
+ @IsOptional()
+ venueTransport?: boolean;
+
+ @IsString()
+ @IsOptional()
+ notes?: string;
+}
diff --git a/backend/src/vips/dto/index.ts b/backend/src/vips/dto/index.ts
new file mode 100644
index 0000000..6ca37f7
--- /dev/null
+++ b/backend/src/vips/dto/index.ts
@@ -0,0 +1,2 @@
+export * from './create-vip.dto';
+export * from './update-vip.dto';
diff --git a/backend/src/vips/dto/update-vip.dto.ts b/backend/src/vips/dto/update-vip.dto.ts
new file mode 100644
index 0000000..0194876
--- /dev/null
+++ b/backend/src/vips/dto/update-vip.dto.ts
@@ -0,0 +1,4 @@
+import { PartialType } from '@nestjs/mapped-types';
+import { CreateVipDto } from './create-vip.dto';
+
+export class UpdateVipDto extends PartialType(CreateVipDto) {}
diff --git a/backend/src/vips/vips.controller.ts b/backend/src/vips/vips.controller.ts
new file mode 100644
index 0000000..8d20258
--- /dev/null
+++ b/backend/src/vips/vips.controller.ts
@@ -0,0 +1,57 @@
+import {
+ Controller,
+ Get,
+ Post,
+ Patch,
+ Delete,
+ Body,
+ Param,
+ Query,
+ UseGuards,
+} from '@nestjs/common';
+import { VipsService } from './vips.service';
+import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
+import { AbilitiesGuard } from '../auth/guards/abilities.guard';
+import { CanCreate, CanRead, CanUpdate, CanDelete } from '../auth/decorators/check-ability.decorator';
+import { CreateVipDto, UpdateVipDto } from './dto';
+
+@Controller('vips')
+@UseGuards(JwtAuthGuard, AbilitiesGuard)
+export class VipsController {
+ constructor(private readonly vipsService: VipsService) {}
+
+ @Post()
+ @CanCreate('VIP')
+ create(@Body() createVipDto: CreateVipDto) {
+ return this.vipsService.create(createVipDto);
+ }
+
+ @Get()
+ @CanRead('VIP')
+ findAll() {
+ return this.vipsService.findAll();
+ }
+
+ @Get(':id')
+ @CanRead('VIP')
+ findOne(@Param('id') id: string) {
+ return this.vipsService.findOne(id);
+ }
+
+ @Patch(':id')
+ @CanUpdate('VIP')
+ update(@Param('id') id: string, @Body() updateVipDto: UpdateVipDto) {
+ return this.vipsService.update(id, updateVipDto);
+ }
+
+ @Delete(':id')
+ @CanDelete('VIP')
+ remove(
+ @Param('id') id: string,
+ @Query('hard') hard?: string,
+ ) {
+ // Only administrators can hard delete
+ const isHardDelete = hard === 'true';
+ return this.vipsService.remove(id, isHardDelete);
+ }
+}
diff --git a/backend/src/vips/vips.module.ts b/backend/src/vips/vips.module.ts
new file mode 100644
index 0000000..0256d52
--- /dev/null
+++ b/backend/src/vips/vips.module.ts
@@ -0,0 +1,10 @@
+import { Module } from '@nestjs/common';
+import { VipsController } from './vips.controller';
+import { VipsService } from './vips.service';
+
+@Module({
+ controllers: [VipsController],
+ providers: [VipsService],
+ exports: [VipsService],
+})
+export class VipsModule {}
diff --git a/backend/src/vips/vips.service.ts b/backend/src/vips/vips.service.ts
new file mode 100644
index 0000000..54117a9
--- /dev/null
+++ b/backend/src/vips/vips.service.ts
@@ -0,0 +1,93 @@
+import { Injectable, NotFoundException, Logger } from '@nestjs/common';
+import { PrismaService } from '../prisma/prisma.service';
+import { CreateVipDto, UpdateVipDto } from './dto';
+
+@Injectable()
+export class VipsService {
+ private readonly logger = new Logger(VipsService.name);
+
+ constructor(private prisma: PrismaService) {}
+
+ async create(createVipDto: CreateVipDto) {
+ this.logger.log(`Creating VIP: ${createVipDto.name}`);
+
+ return this.prisma.vIP.create({
+ data: createVipDto,
+ include: {
+ flights: true,
+ events: {
+ include: { driver: true },
+ },
+ },
+ });
+ }
+
+ async findAll() {
+ return this.prisma.vIP.findMany({
+ where: { deletedAt: null },
+ include: {
+ flights: true,
+ events: {
+ where: { deletedAt: null },
+ include: { driver: true },
+ orderBy: { startTime: 'asc' },
+ },
+ },
+ orderBy: { createdAt: 'desc' },
+ });
+ }
+
+ async findOne(id: string) {
+ const vip = await this.prisma.vIP.findFirst({
+ where: { id, deletedAt: null },
+ include: {
+ flights: true,
+ events: {
+ where: { deletedAt: null },
+ include: { driver: true },
+ orderBy: { startTime: 'asc' },
+ },
+ },
+ });
+
+ if (!vip) {
+ throw new NotFoundException(`VIP with ID ${id} not found`);
+ }
+
+ return vip;
+ }
+
+ async update(id: string, updateVipDto: UpdateVipDto) {
+ const vip = await this.findOne(id);
+
+ this.logger.log(`Updating VIP ${id}: ${vip.name}`);
+
+ return this.prisma.vIP.update({
+ where: { id: vip.id },
+ data: updateVipDto,
+ include: {
+ flights: true,
+ events: {
+ include: { driver: true },
+ },
+ },
+ });
+ }
+
+ async remove(id: string, hardDelete = false) {
+ const vip = await this.findOne(id);
+
+ if (hardDelete) {
+ this.logger.log(`Hard deleting VIP: ${vip.name}`);
+ return this.prisma.vIP.delete({
+ where: { id: vip.id },
+ });
+ }
+
+ this.logger.log(`Soft deleting VIP: ${vip.name}`);
+ return this.prisma.vIP.update({
+ where: { id: vip.id },
+ data: { deletedAt: new Date() },
+ });
+ }
+}
diff --git a/backend/tsconfig.json b/backend/tsconfig.json
index 05f269c..215d67a 100644
--- a/backend/tsconfig.json
+++ b/backend/tsconfig.json
@@ -1,21 +1,24 @@
{
"compilerOptions": {
- "target": "ES2020",
"module": "commonjs",
- "lib": ["ES2020", "DOM"],
- "outDir": "./dist",
- "rootDir": "./src",
- "strict": true,
- "esModuleInterop": true,
- "skipLibCheck": true,
- "forceConsistentCasingInFileNames": true,
- "resolveJsonModule": true,
"declaration": true,
- "declarationMap": true,
+ "removeComments": true,
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
+ "allowSyntheticDefaultImports": true,
+ "target": "ES2021",
"sourceMap": true,
- "types": ["node"],
- "moduleResolution": "node"
- },
- "include": ["src/**/*"],
- "exclude": ["node_modules", "dist"]
+ "outDir": "./dist",
+ "baseUrl": "./",
+ "incremental": true,
+ "skipLibCheck": true,
+ "strictNullChecks": true,
+ "noImplicitAny": true,
+ "strictBindCallApply": false,
+ "forceConsistentCasingInFileNames": false,
+ "noFallthroughCasesInSwitch": false,
+ "paths": {
+ "@/*": ["src/*"]
+ }
+ }
}
diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml
index 0b3e5f1..2c3768e 100644
--- a/docker-compose.dev.yml
+++ b/docker-compose.dev.yml
@@ -11,12 +11,41 @@ services:
- postgres-data:/var/lib/postgresql/data
ports:
- 5432:5432
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -U postgres"]
+ interval: 5s
+ timeout: 5s
+ retries: 5
redis:
image: redis:7
ports:
- 6379:6379
+ keycloak:
+ image: quay.io/keycloak/keycloak:24.0
+ environment:
+ KEYCLOAK_ADMIN: admin
+ KEYCLOAK_ADMIN_PASSWORD: admin
+ KC_DB: postgres
+ KC_DB_URL: jdbc:postgresql://db:5432/keycloak
+ KC_DB_USERNAME: postgres
+ KC_DB_PASSWORD: changeme
+ KC_HOSTNAME_STRICT: false
+ KC_HOSTNAME_STRICT_HTTPS: false
+ KC_HTTP_ENABLED: true
+ ports:
+ - 8080:8080
+ command: start-dev
+ depends_on:
+ db:
+ condition: service_healthy
+ healthcheck:
+ test: ["CMD-SHELL", "curl -f http://localhost:8080/health/ready || exit 1"]
+ interval: 30s
+ timeout: 10s
+ retries: 5
+
backend:
build:
context: ./backend
@@ -24,14 +53,18 @@ services:
environment:
DATABASE_URL: postgresql://postgres:changeme@db:5432/vip_coordinator
REDIS_URL: redis://redis:6379
+ KEYCLOAK_SERVER_URL: http://keycloak:8080
+ KEYCLOAK_REALM: vip-coordinator
+ KEYCLOAK_CLIENT_ID: vip-coordinator-frontend
+ FRONTEND_URL: http://localhost:5173
+ PORT: 3000
+ NODE_ENV: development
ports:
- 3000:3000
depends_on:
- db
- redis
- volumes:
- - ./backend:/app
- - /app/node_modules
+ - keycloak
frontend:
build:
@@ -39,13 +72,13 @@ services:
target: development
environment:
VITE_API_URL: http://localhost:3000/api
+ VITE_KEYCLOAK_URL: http://localhost:8080
+ VITE_KEYCLOAK_REALM: vip-coordinator
+ VITE_KEYCLOAK_CLIENT_ID: vip-coordinator-frontend
ports:
- 5173:5173
depends_on:
- backend
- volumes:
- - ./frontend:/app
- - /app/node_modules
volumes:
postgres-data:
diff --git a/docker-compose.yml b/docker-compose.yml
index 014903c..f78812f 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,57 +1,42 @@
version: '3.8'
services:
-
- db:
- image: postgres:15
+ # PostgreSQL Database
+ postgres:
+ image: postgres:15-alpine
+ container_name: vip-postgres
environment:
+ POSTGRES_USER: postgres
+ POSTGRES_PASSWORD: changeme
POSTGRES_DB: vip_coordinator
- POSTGRES_PASSWORD: ${DB_PASSWORD}
+ ports:
+ - "5433:5432" # Using 5433 on host to avoid conflict
volumes:
- - postgres-data:/var/lib/postgresql/data
- restart: unless-stopped
+ - postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
- interval: 30s
- timeout: 10s
- retries: 3
-
- redis:
- image: redis:7
+ interval: 5s
+ timeout: 5s
+ retries: 5
restart: unless-stopped
+
+ # Redis (Optional - for caching/sessions)
+ redis:
+ image: redis:7-alpine
+ container_name: vip-redis
+ ports:
+ - "6380:6379" # Using 6380 on host to avoid conflicts
+ volumes:
+ - redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
- interval: 30s
- timeout: 10s
- retries: 3
-
- backend:
- image: t72chevy/vip-coordinator:backend-latest
- environment:
- DATABASE_URL: postgresql://postgres:${DB_PASSWORD}@db:5432/vip_coordinator
- REDIS_URL: redis://redis:6379
- GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID}
- GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET}
- GOOGLE_REDIRECT_URI: ${GOOGLE_REDIRECT_URI}
- FRONTEND_URL: ${FRONTEND_URL}
- ADMIN_PASSWORD: ${ADMIN_PASSWORD}
- PORT: 3000
- ports:
- - "3000:3000"
- depends_on:
- db:
- condition: service_healthy
- redis:
- condition: service_healthy
- restart: unless-stopped
-
- frontend:
- image: t72chevy/vip-coordinator:frontend-latest
- ports:
- - "80:80"
- depends_on:
- - backend
+ interval: 5s
+ timeout: 3s
+ retries: 5
restart: unless-stopped
volumes:
- postgres-data:
\ No newline at end of file
+ postgres_data:
+ name: vip_postgres_data
+ redis_data:
+ name: vip_redis_data
diff --git a/frontend/Dockerfile b/frontend-old-20260125/Dockerfile
similarity index 95%
rename from frontend/Dockerfile
rename to frontend-old-20260125/Dockerfile
index 035a960..208fc4f 100644
--- a/frontend/Dockerfile
+++ b/frontend-old-20260125/Dockerfile
@@ -9,6 +9,8 @@ COPY package*.json ./
# Development stage
FROM base AS development
RUN npm install
+# Rebuild native modules for the container architecture
+RUN npm rebuild esbuild
COPY . .
EXPOSE 5173
CMD ["npm", "run", "dev"]
diff --git a/frontend/public/README-API.md b/frontend-old-20260125/dist/README-API.md
similarity index 100%
rename from frontend/public/README-API.md
rename to frontend-old-20260125/dist/README-API.md
diff --git a/frontend/public/api-docs.html b/frontend-old-20260125/dist/api-docs.html
similarity index 100%
rename from frontend/public/api-docs.html
rename to frontend-old-20260125/dist/api-docs.html
diff --git a/frontend/public/api-documentation.yaml b/frontend-old-20260125/dist/api-documentation.yaml
similarity index 100%
rename from frontend/public/api-documentation.yaml
rename to frontend-old-20260125/dist/api-documentation.yaml
diff --git a/frontend-old-20260125/dist/assets/index-a63a7bce.css b/frontend-old-20260125/dist/assets/index-a63a7bce.css
new file mode 100644
index 0000000..bd2a274
--- /dev/null
+++ b/frontend-old-20260125/dist/assets/index-a63a7bce.css
@@ -0,0 +1 @@
+.login-container{display:flex;justify-content:center;align-items:center;min-height:100vh;background:linear-gradient(135deg,#667eea 0%,#764ba2 100%);padding:20px}.login-card{background:white;border-radius:12px;box-shadow:0 20px 40px #0000001a;padding:40px;max-width:400px;width:100%;text-align:center}.login-header h1{color:#333;margin:0 0 8px;font-size:28px;font-weight:600}.login-header p{color:#666;margin:0 0 30px;font-size:16px}.setup-notice{background:#f0f9ff;border:1px solid #0ea5e9;border-radius:8px;padding:20px;margin-bottom:30px}.setup-notice h3{color:#0369a1;margin:0 0 8px;font-size:18px}.setup-notice p{color:#0369a1;margin:0;font-size:14px}.login-content{margin-bottom:30px}.google-login-btn{display:flex;align-items:center;justify-content:center;gap:12px;width:100%;padding:12px 24px;background:white;border:2px solid #dadce0;border-radius:8px;font-size:16px;font-weight:500;color:#3c4043;cursor:pointer;transition:all .2s ease;margin-bottom:20px}.google-login-btn:hover:not(:disabled){border-color:#1a73e8;box-shadow:0 2px 8px #1a73e833}.google-login-btn:disabled{opacity:.6;cursor:not-allowed}.google-icon{width:20px;height:20px}.login-info p{color:#666;font-size:14px;line-height:1.5;margin:0}.dev-login-divider{display:flex;align-items:center;gap:12px;margin:24px 0;color:#94a3b8;font-size:12px;text-transform:uppercase;letter-spacing:.08em}.dev-login-divider:before,.dev-login-divider:after{content:"";flex:1;height:1px;background:#e2e8f0}.dev-login-form{display:flex;flex-direction:column;gap:16px;text-align:left}.dev-login-form h3{margin:0;color:#1e293b;font-size:18px;font-weight:600}.dev-login-hint{margin:0;font-size:13px;color:#64748b;line-height:1.4}.dev-login-form label{display:flex;flex-direction:column;gap:6px;font-size:14px;color:#334155}.dev-login-form input{width:100%;padding:10px 12px;border:1px solid #cbd5f5;border-radius:8px;font-size:14px;transition:border-color .2s ease,box-shadow .2s ease}.dev-login-form input:focus{outline:none;border-color:#2563eb;box-shadow:0 0 0 3px #2563eb26}.dev-login-error{background:#fee2e2;border:1px solid #fecaca;color:#dc2626;padding:10px 12px;border-radius:8px;font-size:13px}.dev-login-button{width:100%;padding:12px;border:none;border-radius:8px;background:linear-gradient(135deg,#2563eb 0%,#1d4ed8 100%);color:#fff;font-size:15px;font-weight:600;cursor:pointer;transition:transform .2s ease,box-shadow .2s ease}.dev-login-button:hover:not(:disabled){transform:translateY(-1px);box-shadow:0 10px 20px #2563eb33}.dev-login-button:disabled{opacity:.7;cursor:not-allowed}.login-footer{border-top:1px solid #eee;padding-top:20px}.login-footer p{color:#999;font-size:12px;margin:0}.loading{color:#666;font-size:16px;padding:40px}@media (max-width: 480px){.login-container{padding:10px}.login-card{padding:30px 20px}.login-header h1{font-size:24px}}.btn-modern{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));border-radius:.75rem;padding:.75rem 1.5rem;font-size:.875rem;line-height:1.25rem;font-weight:600;--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow);transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.btn-modern:hover{--tw-translate-y: -.125rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.btn-gradient-blue{background-image:linear-gradient(to right,var(--tw-gradient-stops));--tw-gradient-from: #3b82f6 var(--tw-gradient-from-position);--tw-gradient-to: rgb(59 130 246 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);--tw-gradient-to: #2563eb var(--tw-gradient-to-position);--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.btn-gradient-blue:hover{--tw-gradient-from: #2563eb var(--tw-gradient-from-position);--tw-gradient-to: rgb(37 99 235 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);--tw-gradient-to: #1d4ed8 var(--tw-gradient-to-position)}.btn-gradient-green{background-image:linear-gradient(to right,var(--tw-gradient-stops));--tw-gradient-from: #22c55e var(--tw-gradient-from-position);--tw-gradient-to: rgb(34 197 94 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);--tw-gradient-to: #16a34a var(--tw-gradient-to-position);--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.btn-gradient-green:hover{--tw-gradient-from: #16a34a var(--tw-gradient-from-position);--tw-gradient-to: rgb(22 163 74 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);--tw-gradient-to: #15803d var(--tw-gradient-to-position)}.btn-gradient-purple{background-image:linear-gradient(to right,var(--tw-gradient-stops));--tw-gradient-from: #a855f7 var(--tw-gradient-from-position);--tw-gradient-to: rgb(168 85 247 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);--tw-gradient-to: #9333ea var(--tw-gradient-to-position);--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.btn-gradient-purple:hover{--tw-gradient-from: #9333ea var(--tw-gradient-from-position);--tw-gradient-to: rgb(147 51 234 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);--tw-gradient-to: #7e22ce var(--tw-gradient-to-position)}.btn-gradient-amber{background-image:linear-gradient(to right,var(--tw-gradient-stops));--tw-gradient-from: #f59e0b var(--tw-gradient-from-position);--tw-gradient-to: rgb(245 158 11 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);--tw-gradient-to: #d97706 var(--tw-gradient-to-position);--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.btn-gradient-amber:hover{--tw-gradient-from: #d97706 var(--tw-gradient-from-position);--tw-gradient-to: rgb(217 119 6 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);--tw-gradient-to: #b45309 var(--tw-gradient-to-position)}.status-badge{display:inline-flex;align-items:center;border-radius:9999px;padding:.25rem .75rem;font-size:.75rem;line-height:1rem;font-weight:600}.status-scheduled{border-width:1px;--tw-border-opacity: 1;border-color:rgb(191 219 254 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(219 234 254 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(30 64 175 / var(--tw-text-opacity, 1))}.status-in-progress{border-width:1px;--tw-border-opacity: 1;border-color:rgb(253 230 138 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(254 243 199 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(146 64 14 / var(--tw-text-opacity, 1))}.status-completed{border-width:1px;--tw-border-opacity: 1;border-color:rgb(187 247 208 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(220 252 231 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(22 101 52 / var(--tw-text-opacity, 1))}.status-cancelled{border-width:1px;--tw-border-opacity: 1;border-color:rgb(254 202 202 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(254 226 226 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(153 27 27 / var(--tw-text-opacity, 1))}.card-modern{overflow:hidden;border-radius:1rem;border-width:1px;border-color:#e2e8f099;--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1));--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow);--tw-backdrop-blur: blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.card-header{border-bottom-width:1px;border-color:#e2e8f099;background-image:linear-gradient(to right,var(--tw-gradient-stops));--tw-gradient-from: #f8fafc var(--tw-gradient-from-position);--tw-gradient-to: rgb(248 250 252 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);--tw-gradient-to: #f1f5f9 var(--tw-gradient-to-position);padding:1rem 1.5rem}.card-content{padding:1.5rem}.loading-spinner{animation:spin 1s linear infinite;border-radius:9999px;border-width:4px;--tw-border-opacity: 1;border-color:rgb(37 99 235 / var(--tw-border-opacity, 1));border-top-color:transparent}.loading-text{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite;--tw-text-opacity: 1;color:rgb(71 85 105 / var(--tw-text-opacity, 1))}.skeleton{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite;border-radius:.25rem;--tw-bg-opacity: 1;background-color:rgb(226 232 240 / var(--tw-bg-opacity, 1))}.form-modern>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem * var(--tw-space-y-reverse))}.form-group-modern>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.form-label-modern{display:block;font-size:.875rem;line-height:1.25rem;font-weight:600;--tw-text-opacity: 1;color:rgb(51 65 85 / var(--tw-text-opacity, 1))}.form-input-modern{width:100%;border-radius:.75rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(203 213 225 / var(--tw-border-opacity, 1));padding:.75rem 1rem;--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow);transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.form-input-modern:focus{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1));outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.form-select-modern{width:100%;border-radius:.75rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(203 213 225 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1));padding:.75rem 1rem;--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow);transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.form-select-modern:focus{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1));outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.animate-fade-in{animation:fadeIn .5s ease-in-out}.animate-slide-up{animation:slideUp .3s ease-out}.animate-scale-in{animation:scaleIn .2s ease-out}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideUp{0%{transform:translateY(10px);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes scaleIn{0%{transform:scale(.95);opacity:0}to{transform:scale(1);opacity:1}}@media (max-width: 768px){.mobile-stack{flex-direction:column}.mobile-stack>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse));--tw-space-x-reverse: 0;margin-right:calc(0px * var(--tw-space-x-reverse));margin-left:calc(0px * calc(1 - var(--tw-space-x-reverse)))}.mobile-full{width:100%}.mobile-text-center{text-align:center}}.glass{border-width:1px;border-color:#fff3;background-color:#fffc;--tw-backdrop-blur: blur(16px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.glass-dark{border-width:1px;border-color:#33415533;background-color:#0f172acc;--tw-backdrop-blur: blur(16px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.hover-lift{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.hover-lift:hover{--tw-translate-y: -.25rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover-glow{transition-property:box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.hover-glow:hover{--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / .25);--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.hover-scale{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.hover-scale:hover{--tw-scale-x: 1.05;--tw-scale-y: 1.05;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}:root{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,sans-serif;line-height:1.6;font-weight:400;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-text-size-adjust:100%}*{box-sizing:border-box}body{margin:0;min-width:320px;min-height:100vh;background:linear-gradient(135deg,#f8fafc 0%,#e2e8f0 100%);color:#1e293b}#root{width:100%;margin:0 auto;text-align:left}html{scroll-behavior:smooth}*:focus{outline:2px solid #3b82f6;outline-offset:2px}.container{width:100%}@media (min-width: 640px){.container{max-width:640px}}@media (min-width: 768px){.container{max-width:768px}}@media (min-width: 1024px){.container{max-width:1024px}}@media (min-width: 1280px){.container{max-width:1280px}}@media (min-width: 1536px){.container{max-width:1536px}}.btn{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));border-radius:.75rem;padding:.75rem 1.5rem;font-size:.875rem;line-height:1.25rem;font-weight:600;--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow);transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.btn:hover{--tw-translate-y: -.125rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.btn:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-offset-width: 2px}.btn-primary{background-image:linear-gradient(to right,var(--tw-gradient-stops));--tw-gradient-from: #3b82f6 var(--tw-gradient-from-position);--tw-gradient-to: rgb(59 130 246 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);--tw-gradient-to: #2563eb var(--tw-gradient-to-position);--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.btn-primary:hover{--tw-gradient-from: #2563eb var(--tw-gradient-from-position);--tw-gradient-to: rgb(37 99 235 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);--tw-gradient-to: #1d4ed8 var(--tw-gradient-to-position)}.btn-primary:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.btn-secondary{background-image:linear-gradient(to right,var(--tw-gradient-stops));--tw-gradient-from: #64748b var(--tw-gradient-from-position);--tw-gradient-to: rgb(100 116 139 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);--tw-gradient-to: #475569 var(--tw-gradient-to-position);--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.btn-secondary:hover{--tw-gradient-from: #475569 var(--tw-gradient-from-position);--tw-gradient-to: rgb(71 85 105 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);--tw-gradient-to: #334155 var(--tw-gradient-to-position)}.btn-secondary:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(100 116 139 / var(--tw-ring-opacity, 1))}.btn-danger{background-image:linear-gradient(to right,var(--tw-gradient-stops));--tw-gradient-from: #ef4444 var(--tw-gradient-from-position);--tw-gradient-to: rgb(239 68 68 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);--tw-gradient-to: #dc2626 var(--tw-gradient-to-position);--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.btn-danger:hover{--tw-gradient-from: #dc2626 var(--tw-gradient-from-position);--tw-gradient-to: rgb(220 38 38 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);--tw-gradient-to: #b91c1c var(--tw-gradient-to-position)}.btn-danger:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(239 68 68 / var(--tw-ring-opacity, 1))}.btn-success{background-image:linear-gradient(to right,var(--tw-gradient-stops));--tw-gradient-from: #22c55e var(--tw-gradient-from-position);--tw-gradient-to: rgb(34 197 94 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);--tw-gradient-to: #16a34a var(--tw-gradient-to-position);--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.btn-success:hover{--tw-gradient-from: #16a34a var(--tw-gradient-from-position);--tw-gradient-to: rgb(22 163 74 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);--tw-gradient-to: #15803d var(--tw-gradient-to-position)}.btn-success:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(34 197 94 / var(--tw-ring-opacity, 1))}.card{overflow:hidden;border-radius:1rem;border-width:1px;border-color:#e2e8f099;--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1));--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow);--tw-backdrop-blur: blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.form-group{margin-bottom:1.5rem}.form-label{margin-bottom:.75rem;display:block;font-size:.875rem;line-height:1.25rem;font-weight:600;--tw-text-opacity: 1;color:rgb(51 65 85 / var(--tw-text-opacity, 1))}.form-input{width:100%;border-radius:.75rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(203 213 225 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1));padding:.75rem 1rem;--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow);transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.form-input:focus{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1));outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.form-select{width:100%;border-radius:.75rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(203 213 225 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1));padding:.75rem 1rem;--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow);transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.form-select:focus{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1));outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.form-textarea{width:100%;resize:none;border-radius:.75rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(203 213 225 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1));padding:.75rem 1rem;--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow);transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.form-textarea:focus{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1));outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.form-checkbox{height:1.25rem;width:1.25rem;border-radius:.25rem;--tw-border-opacity: 1;border-color:rgb(203 213 225 / var(--tw-border-opacity, 1));--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity, 1))}.form-checkbox:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.form-radio{height:1rem;width:1rem;--tw-border-opacity: 1;border-color:rgb(203 213 225 / var(--tw-border-opacity, 1));--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity, 1))}.form-radio:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.modal-overlay{position:fixed;top:0;right:0;bottom:0;left:0;z-index:50;display:flex;align-items:center;justify-content:center;background-color:#00000080;padding:1rem;--tw-backdrop-blur: blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.modal-content{max-height:90vh;width:100%;max-width:56rem;overflow-y:auto;border-radius:1rem;--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1));--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / .25);--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.modal-header{border-bottom-width:1px;border-color:#e2e8f099;background-image:linear-gradient(to right,var(--tw-gradient-stops));--tw-gradient-from: #eff6ff var(--tw-gradient-from-position);--tw-gradient-to: rgb(239 246 255 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);--tw-gradient-to: #eef2ff var(--tw-gradient-to-position);padding:1.5rem 2rem}.modal-body{padding:2rem}.form-actions{margin-top:2rem;display:flex;justify-content:flex-end}.form-actions>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(1rem * var(--tw-space-x-reverse));margin-left:calc(1rem * calc(1 - var(--tw-space-x-reverse)))}.form-actions{border-top-width:1px;border-color:#e2e8f099;padding-top:1.5rem}.form-section{margin-bottom:1.5rem;border-radius:.75rem;border-width:1px;border-color:#e2e8f099;--tw-bg-opacity: 1;background-color:rgb(248 250 252 / var(--tw-bg-opacity, 1));padding:1.5rem}.form-section-header{margin-bottom:1rem;display:flex;align-items:center;justify-content:space-between}.form-section-title{font-size:1.125rem;line-height:1.75rem;font-weight:700;--tw-text-opacity: 1;color:rgb(30 41 59 / var(--tw-text-opacity, 1))}.radio-group{margin-top:.75rem;display:flex;gap:1.5rem}.radio-option{display:flex;cursor:pointer;align-items:center;border-radius:.5rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(226 232 240 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1));padding:.75rem 1rem;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.radio-option:hover{--tw-border-opacity: 1;border-color:rgb(147 197 253 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1))}.radio-option.selected{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1));--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-opacity: 1;--tw-ring-color: rgb(191 219 254 / var(--tw-ring-opacity, 1))}.checkbox-option{display:flex;cursor:pointer;align-items:center;border-radius:.5rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(226 232 240 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1));padding:.75rem 1rem;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.checkbox-option:hover{--tw-border-opacity: 1;border-color:rgb(147 197 253 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1))}.checkbox-option.checked{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1))}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{top:0;right:0;bottom:0;left:0}.right-2{right:.5rem}.top-0{top:0}.top-2{top:.5rem}.z-50{z-index:50}.mx-auto{margin-left:auto;margin-right:auto}.-mb-px{margin-bottom:-1px}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.ml-2{margin-left:.5rem}.ml-4{margin-left:1rem}.ml-6{margin-left:1.5rem}.ml-auto{margin-left:auto}.mr-2{margin-right:.5rem}.mr-3{margin-right:.75rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.hidden{display:none}.h-10{height:2.5rem}.h-12{height:3rem}.h-16{height:4rem}.h-2{height:.5rem}.h-20{height:5rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-8{height:2rem}.max-h-20{max-height:5rem}.max-h-\[90vh\]{max-height:90vh}.min-h-64{min-height:16rem}.min-h-screen{min-height:100vh}.w-1\/4{width:25%}.w-10{width:2.5rem}.w-12{width:3rem}.w-16{width:4rem}.w-2{width:.5rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-8{width:2rem}.w-full{width:100%}.max-w-2xl{max-width:42rem}.max-w-4xl{max-width:56rem}.max-w-7xl{max-width:80rem}.max-w-xl{max-width:36rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.list-inside{list-style-position:inside}.list-decimal{list-style-type:decimal}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.gap-8{gap:2rem}.space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(.25rem * var(--tw-space-x-reverse));margin-left:calc(.25rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(.5rem * var(--tw-space-x-reverse));margin-left:calc(.5rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(.75rem * var(--tw-space-x-reverse));margin-left:calc(.75rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(1rem * var(--tw-space-x-reverse));margin-left:calc(1rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-8>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(2rem * var(--tw-space-x-reverse));margin-left:calc(2rem * calc(1 - var(--tw-space-x-reverse)))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem * var(--tw-space-y-reverse))}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(2rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2rem * var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.divide-gray-200>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgb(229 231 235 / var(--tw-divide-opacity, 1))}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:1rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-2{border-width:2px}.border-4{border-width:4px}.border-b{border-bottom-width:1px}.border-b-2{border-bottom-width:2px}.border-t{border-top-width:1px}.border-amber-200{--tw-border-opacity: 1;border-color:rgb(253 230 138 / var(--tw-border-opacity, 1))}.border-amber-200\/60{border-color:#fde68a99}.border-amber-300{--tw-border-opacity: 1;border-color:rgb(252 211 77 / var(--tw-border-opacity, 1))}.border-blue-200{--tw-border-opacity: 1;border-color:rgb(191 219 254 / var(--tw-border-opacity, 1))}.border-blue-200\/60{border-color:#bfdbfe99}.border-blue-300{--tw-border-opacity: 1;border-color:rgb(147 197 253 / var(--tw-border-opacity, 1))}.border-blue-500{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1))}.border-blue-600{--tw-border-opacity: 1;border-color:rgb(37 99 235 / var(--tw-border-opacity, 1))}.border-gray-200{--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity, 1))}.border-green-200{--tw-border-opacity: 1;border-color:rgb(187 247 208 / var(--tw-border-opacity, 1))}.border-green-200\/60{border-color:#bbf7d099}.border-green-500{--tw-border-opacity: 1;border-color:rgb(34 197 94 / var(--tw-border-opacity, 1))}.border-orange-200{--tw-border-opacity: 1;border-color:rgb(254 215 170 / var(--tw-border-opacity, 1))}.border-orange-500{--tw-border-opacity: 1;border-color:rgb(249 115 22 / var(--tw-border-opacity, 1))}.border-red-200{--tw-border-opacity: 1;border-color:rgb(254 202 202 / var(--tw-border-opacity, 1))}.border-red-200\/60{border-color:#fecaca99}.border-red-600{--tw-border-opacity: 1;border-color:rgb(220 38 38 / var(--tw-border-opacity, 1))}.border-rose-200\/70{border-color:#fecdd3b3}.border-slate-200{--tw-border-opacity: 1;border-color:rgb(226 232 240 / var(--tw-border-opacity, 1))}.border-slate-200\/50{border-color:#e2e8f080}.border-slate-200\/60{border-color:#e2e8f099}.border-slate-300{--tw-border-opacity: 1;border-color:rgb(203 213 225 / var(--tw-border-opacity, 1))}.border-transparent{border-color:transparent}.border-white{--tw-border-opacity: 1;border-color:rgb(255 255 255 / var(--tw-border-opacity, 1))}.border-t-transparent{border-top-color:transparent}.bg-amber-100{--tw-bg-opacity: 1;background-color:rgb(254 243 199 / var(--tw-bg-opacity, 1))}.bg-amber-50{--tw-bg-opacity: 1;background-color:rgb(255 251 235 / var(--tw-bg-opacity, 1))}.bg-black\/50{background-color:#00000080}.bg-blue-100{--tw-bg-opacity: 1;background-color:rgb(219 234 254 / var(--tw-bg-opacity, 1))}.bg-blue-50{--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1))}.bg-blue-500{--tw-bg-opacity: 1;background-color:rgb(59 130 246 / var(--tw-bg-opacity, 1))}.bg-gray-100{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.bg-gray-200{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.bg-gray-300{--tw-bg-opacity: 1;background-color:rgb(209 213 219 / var(--tw-bg-opacity, 1))}.bg-gray-50{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.bg-green-100{--tw-bg-opacity: 1;background-color:rgb(220 252 231 / var(--tw-bg-opacity, 1))}.bg-green-50{--tw-bg-opacity: 1;background-color:rgb(240 253 244 / var(--tw-bg-opacity, 1))}.bg-green-500{--tw-bg-opacity: 1;background-color:rgb(34 197 94 / var(--tw-bg-opacity, 1))}.bg-green-600{--tw-bg-opacity: 1;background-color:rgb(22 163 74 / var(--tw-bg-opacity, 1))}.bg-orange-100{--tw-bg-opacity: 1;background-color:rgb(255 237 213 / var(--tw-bg-opacity, 1))}.bg-orange-50{--tw-bg-opacity: 1;background-color:rgb(255 247 237 / var(--tw-bg-opacity, 1))}.bg-purple-100{--tw-bg-opacity: 1;background-color:rgb(243 232 255 / var(--tw-bg-opacity, 1))}.bg-red-100{--tw-bg-opacity: 1;background-color:rgb(254 226 226 / var(--tw-bg-opacity, 1))}.bg-red-50{--tw-bg-opacity: 1;background-color:rgb(254 242 242 / var(--tw-bg-opacity, 1))}.bg-red-600{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity, 1))}.bg-slate-100{--tw-bg-opacity: 1;background-color:rgb(241 245 249 / var(--tw-bg-opacity, 1))}.bg-slate-200{--tw-bg-opacity: 1;background-color:rgb(226 232 240 / var(--tw-bg-opacity, 1))}.bg-slate-300{--tw-bg-opacity: 1;background-color:rgb(203 213 225 / var(--tw-bg-opacity, 1))}.bg-slate-50{--tw-bg-opacity: 1;background-color:rgb(248 250 252 / var(--tw-bg-opacity, 1))}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.bg-white\/50{background-color:#ffffff80}.bg-white\/80{background-color:#fffc}.bg-gradient-to-br{background-image:linear-gradient(to bottom right,var(--tw-gradient-stops))}.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.from-amber-50{--tw-gradient-from: #fffbeb var(--tw-gradient-from-position);--tw-gradient-to: rgb(255 251 235 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-amber-500{--tw-gradient-from: #f59e0b var(--tw-gradient-from-position);--tw-gradient-to: rgb(245 158 11 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-blue-50{--tw-gradient-from: #eff6ff var(--tw-gradient-from-position);--tw-gradient-to: rgb(239 246 255 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-blue-500{--tw-gradient-from: #3b82f6 var(--tw-gradient-from-position);--tw-gradient-to: rgb(59 130 246 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-blue-600{--tw-gradient-from: #2563eb var(--tw-gradient-from-position);--tw-gradient-to: rgb(37 99 235 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-green-400{--tw-gradient-from: #4ade80 var(--tw-gradient-from-position);--tw-gradient-to: rgb(74 222 128 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-green-50{--tw-gradient-from: #f0fdf4 var(--tw-gradient-from-position);--tw-gradient-to: rgb(240 253 244 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-green-500{--tw-gradient-from: #22c55e var(--tw-gradient-from-position);--tw-gradient-to: rgb(34 197 94 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-indigo-50{--tw-gradient-from: #eef2ff var(--tw-gradient-from-position);--tw-gradient-to: rgb(238 242 255 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-orange-50{--tw-gradient-from: #fff7ed var(--tw-gradient-from-position);--tw-gradient-to: rgb(255 247 237 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-purple-50{--tw-gradient-from: #faf5ff var(--tw-gradient-from-position);--tw-gradient-to: rgb(250 245 255 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-purple-500{--tw-gradient-from: #a855f7 var(--tw-gradient-from-position);--tw-gradient-to: rgb(168 85 247 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-red-500{--tw-gradient-from: #ef4444 var(--tw-gradient-from-position);--tw-gradient-to: rgb(239 68 68 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-sky-50{--tw-gradient-from: #f0f9ff var(--tw-gradient-from-position);--tw-gradient-to: rgb(240 249 255 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-slate-400{--tw-gradient-from: #94a3b8 var(--tw-gradient-from-position);--tw-gradient-to: rgb(148 163 184 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-slate-50{--tw-gradient-from: #f8fafc var(--tw-gradient-from-position);--tw-gradient-to: rgb(248 250 252 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-slate-500{--tw-gradient-from: #64748b var(--tw-gradient-from-position);--tw-gradient-to: rgb(100 116 139 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-slate-600{--tw-gradient-from: #475569 var(--tw-gradient-from-position);--tw-gradient-to: rgb(71 85 105 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-slate-800{--tw-gradient-from: #1e293b var(--tw-gradient-from-position);--tw-gradient-to: rgb(30 41 59 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.via-blue-50{--tw-gradient-to: rgb(239 246 255 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), #eff6ff var(--tw-gradient-via-position), var(--tw-gradient-to)}.to-blue-50{--tw-gradient-to: #eff6ff var(--tw-gradient-to-position)}.to-blue-600{--tw-gradient-to: #2563eb var(--tw-gradient-to-position)}.to-emerald-50{--tw-gradient-to: #ecfdf5 var(--tw-gradient-to-position)}.to-green-600{--tw-gradient-to: #16a34a var(--tw-gradient-to-position)}.to-indigo-50{--tw-gradient-to: #eef2ff var(--tw-gradient-to-position)}.to-indigo-600{--tw-gradient-to: #4f46e5 var(--tw-gradient-to-position)}.to-orange-50{--tw-gradient-to: #fff7ed var(--tw-gradient-to-position)}.to-orange-500{--tw-gradient-to: #f97316 var(--tw-gradient-to-position)}.to-pink-50{--tw-gradient-to: #fdf2f8 var(--tw-gradient-to-position)}.to-purple-50{--tw-gradient-to: #faf5ff var(--tw-gradient-to-position)}.to-purple-600{--tw-gradient-to: #9333ea var(--tw-gradient-to-position)}.to-red-50{--tw-gradient-to: #fef2f2 var(--tw-gradient-to-position)}.to-red-600{--tw-gradient-to: #dc2626 var(--tw-gradient-to-position)}.to-rose-50{--tw-gradient-to: #fff1f2 var(--tw-gradient-to-position)}.to-slate-100{--tw-gradient-to: #f1f5f9 var(--tw-gradient-to-position)}.to-slate-600{--tw-gradient-to: #475569 var(--tw-gradient-to-position)}.to-slate-700{--tw-gradient-to: #334155 var(--tw-gradient-to-position)}.bg-clip-text{-webkit-background-clip:text;background-clip:text}.object-cover{-o-object-fit:cover;object-fit:cover}.p-12{padding:3rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-8{padding-left:2rem;padding-right:2rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pt-4{padding-top:1rem}.pt-6{padding-top:1.5rem}.text-center{text-align:center}.text-right{text-align:right}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-6xl{font-size:3.75rem;line-height:1}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.capitalize{text-transform:capitalize}.italic{font-style:italic}.text-amber-600{--tw-text-opacity: 1;color:rgb(217 119 6 / var(--tw-text-opacity, 1))}.text-amber-700{--tw-text-opacity: 1;color:rgb(180 83 9 / var(--tw-text-opacity, 1))}.text-amber-800{--tw-text-opacity: 1;color:rgb(146 64 14 / var(--tw-text-opacity, 1))}.text-amber-900{--tw-text-opacity: 1;color:rgb(120 53 15 / var(--tw-text-opacity, 1))}.text-blue-600{--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity, 1))}.text-blue-700{--tw-text-opacity: 1;color:rgb(29 78 216 / var(--tw-text-opacity, 1))}.text-blue-800{--tw-text-opacity: 1;color:rgb(30 64 175 / var(--tw-text-opacity, 1))}.text-blue-900{--tw-text-opacity: 1;color:rgb(30 58 138 / var(--tw-text-opacity, 1))}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.text-gray-600{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.text-gray-800{--tw-text-opacity: 1;color:rgb(31 41 55 / var(--tw-text-opacity, 1))}.text-gray-900{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity, 1))}.text-green-600{--tw-text-opacity: 1;color:rgb(22 163 74 / var(--tw-text-opacity, 1))}.text-green-700{--tw-text-opacity: 1;color:rgb(21 128 61 / var(--tw-text-opacity, 1))}.text-green-800{--tw-text-opacity: 1;color:rgb(22 101 52 / var(--tw-text-opacity, 1))}.text-green-900{--tw-text-opacity: 1;color:rgb(20 83 45 / var(--tw-text-opacity, 1))}.text-orange-600{--tw-text-opacity: 1;color:rgb(234 88 12 / var(--tw-text-opacity, 1))}.text-orange-800{--tw-text-opacity: 1;color:rgb(154 52 18 / var(--tw-text-opacity, 1))}.text-orange-900{--tw-text-opacity: 1;color:rgb(124 45 18 / var(--tw-text-opacity, 1))}.text-purple-800{--tw-text-opacity: 1;color:rgb(107 33 168 / var(--tw-text-opacity, 1))}.text-red-500{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.text-red-600{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.text-red-700{--tw-text-opacity: 1;color:rgb(185 28 28 / var(--tw-text-opacity, 1))}.text-red-800{--tw-text-opacity: 1;color:rgb(153 27 27 / var(--tw-text-opacity, 1))}.text-red-900{--tw-text-opacity: 1;color:rgb(127 29 29 / var(--tw-text-opacity, 1))}.text-rose-700{--tw-text-opacity: 1;color:rgb(190 18 60 / var(--tw-text-opacity, 1))}.text-slate-400{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity, 1))}.text-slate-500{--tw-text-opacity: 1;color:rgb(100 116 139 / var(--tw-text-opacity, 1))}.text-slate-600{--tw-text-opacity: 1;color:rgb(71 85 105 / var(--tw-text-opacity, 1))}.text-slate-700{--tw-text-opacity: 1;color:rgb(51 65 85 / var(--tw-text-opacity, 1))}.text-slate-800{--tw-text-opacity: 1;color:rgb(30 41 59 / var(--tw-text-opacity, 1))}.text-slate-900{--tw-text-opacity: 1;color:rgb(15 23 42 / var(--tw-text-opacity, 1))}.text-transparent{color:transparent}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.opacity-50{opacity:.5}.shadow-2xl{--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / .25);--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-lg{--tw-backdrop-blur: blur(16px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-sm{--tw-backdrop-blur: blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-shadow{transition-property:box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}.hover\:border-gray-300:hover{--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1))}.hover\:border-slate-300:hover{--tw-border-opacity: 1;border-color:rgb(203 213 225 / var(--tw-border-opacity, 1))}.hover\:border-slate-400:hover{--tw-border-opacity: 1;border-color:rgb(148 163 184 / var(--tw-border-opacity, 1))}.hover\:bg-amber-50:hover{--tw-bg-opacity: 1;background-color:rgb(255 251 235 / var(--tw-bg-opacity, 1))}.hover\:bg-blue-50:hover{--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-50:hover{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.hover\:bg-green-700:hover{--tw-bg-opacity: 1;background-color:rgb(21 128 61 / var(--tw-bg-opacity, 1))}.hover\:bg-purple-50:hover{--tw-bg-opacity: 1;background-color:rgb(250 245 255 / var(--tw-bg-opacity, 1))}.hover\:bg-red-100:hover{--tw-bg-opacity: 1;background-color:rgb(254 226 226 / var(--tw-bg-opacity, 1))}.hover\:bg-red-50:hover{--tw-bg-opacity: 1;background-color:rgb(254 242 242 / var(--tw-bg-opacity, 1))}.hover\:bg-red-700:hover{--tw-bg-opacity: 1;background-color:rgb(185 28 28 / var(--tw-bg-opacity, 1))}.hover\:bg-slate-200:hover{--tw-bg-opacity: 1;background-color:rgb(226 232 240 / var(--tw-bg-opacity, 1))}.hover\:bg-slate-50:hover{--tw-bg-opacity: 1;background-color:rgb(248 250 252 / var(--tw-bg-opacity, 1))}.hover\:bg-opacity-80:hover{--tw-bg-opacity: .8}.hover\:from-amber-600:hover{--tw-gradient-from: #d97706 var(--tw-gradient-from-position);--tw-gradient-to: rgb(217 119 6 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.hover\:from-blue-600:hover{--tw-gradient-from: #2563eb var(--tw-gradient-from-position);--tw-gradient-to: rgb(37 99 235 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.hover\:from-green-600:hover{--tw-gradient-from: #16a34a var(--tw-gradient-from-position);--tw-gradient-to: rgb(22 163 74 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.hover\:from-purple-600:hover{--tw-gradient-from: #9333ea var(--tw-gradient-from-position);--tw-gradient-to: rgb(147 51 234 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.hover\:from-red-600:hover{--tw-gradient-from: #dc2626 var(--tw-gradient-from-position);--tw-gradient-to: rgb(220 38 38 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.hover\:from-slate-600:hover{--tw-gradient-from: #475569 var(--tw-gradient-from-position);--tw-gradient-to: rgb(71 85 105 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.hover\:to-blue-700:hover{--tw-gradient-to: #1d4ed8 var(--tw-gradient-to-position)}.hover\:to-green-700:hover{--tw-gradient-to: #15803d var(--tw-gradient-to-position)}.hover\:to-orange-600:hover{--tw-gradient-to: #ea580c var(--tw-gradient-to-position)}.hover\:to-purple-700:hover{--tw-gradient-to: #7e22ce var(--tw-gradient-to-position)}.hover\:to-red-700:hover{--tw-gradient-to: #b91c1c var(--tw-gradient-to-position)}.hover\:to-slate-700:hover{--tw-gradient-to: #334155 var(--tw-gradient-to-position)}.hover\:text-amber-600:hover{--tw-text-opacity: 1;color:rgb(217 119 6 / var(--tw-text-opacity, 1))}.hover\:text-blue-600:hover{--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity, 1))}.hover\:text-gray-700:hover{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.hover\:text-purple-600:hover{--tw-text-opacity: 1;color:rgb(147 51 234 / var(--tw-text-opacity, 1))}.hover\:text-red-700:hover{--tw-text-opacity: 1;color:rgb(185 28 28 / var(--tw-text-opacity, 1))}.hover\:text-red-800:hover{--tw-text-opacity: 1;color:rgb(153 27 27 / var(--tw-text-opacity, 1))}.hover\:shadow-lg:hover{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.hover\:shadow-md:hover{--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.hover\:shadow-xl:hover{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.focus\:border-blue-500:focus{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1))}.focus\:border-green-500:focus{--tw-border-opacity: 1;border-color:rgb(34 197 94 / var(--tw-border-opacity, 1))}.focus\:ring-2:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-blue-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.focus\:ring-green-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(34 197 94 / var(--tw-ring-opacity, 1))}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:from-slate-400:disabled{--tw-gradient-from: #94a3b8 var(--tw-gradient-from-position);--tw-gradient-to: rgb(148 163 184 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.disabled\:to-slate-500:disabled{--tw-gradient-to: #64748b var(--tw-gradient-to-position)}.disabled\:opacity-50:disabled{opacity:.5}@media (min-width: 640px){.sm\:flex{display:flex}}@media (min-width: 768px){.md\:col-span-2{grid-column:span 2 / span 2}.md\:flex{display:flex}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}@media (min-width: 1024px){.lg\:col-span-2{grid-column:span 2 / span 2}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:px-8{padding-left:2rem;padding-right:2rem}}@media (min-width: 1280px){.xl\:col-span-2{grid-column:span 2 / span 2}.xl\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}
diff --git a/frontend-old-20260125/dist/assets/index-b3227753.js b/frontend-old-20260125/dist/assets/index-b3227753.js
new file mode 100644
index 0000000..42c7f8d
--- /dev/null
+++ b/frontend-old-20260125/dist/assets/index-b3227753.js
@@ -0,0 +1,651 @@
+function vh(e,t){for(var n=0;nr[s]})}}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const s of document.querySelectorAll('link[rel="modulepreload"]'))r(s);new MutationObserver(s=>{for(const o of s)if(o.type==="childList")for(const a of o.addedNodes)a.tagName==="LINK"&&a.rel==="modulepreload"&&r(a)}).observe(document,{childList:!0,subtree:!0});function n(s){const o={};return s.integrity&&(o.integrity=s.integrity),s.referrerPolicy&&(o.referrerPolicy=s.referrerPolicy),s.crossOrigin==="use-credentials"?o.credentials="include":s.crossOrigin==="anonymous"?o.credentials="omit":o.credentials="same-origin",o}function r(s){if(s.ep)return;s.ep=!0;const o=n(s);fetch(s.href,o)}})();function yh(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var _c={exports:{}},Ks={},Dc={exports:{}},R={};/**
+ * @license React
+ * react.production.min.js
+ *
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */var zr=Symbol.for("react.element"),wh=Symbol.for("react.portal"),bh=Symbol.for("react.fragment"),jh=Symbol.for("react.strict_mode"),Nh=Symbol.for("react.profiler"),kh=Symbol.for("react.provider"),Sh=Symbol.for("react.context"),Ch=Symbol.for("react.forward_ref"),Eh=Symbol.for("react.suspense"),Th=Symbol.for("react.memo"),Ph=Symbol.for("react.lazy"),Ja=Symbol.iterator;function _h(e){return e===null||typeof e!="object"?null:(e=Ja&&e[Ja]||e["@@iterator"],typeof e=="function"?e:null)}var Ic={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},Ac=Object.assign,zc={};function $n(e,t,n){this.props=e,this.context=t,this.refs=zc,this.updater=n||Ic}$n.prototype.isReactComponent={};$n.prototype.setState=function(e,t){if(typeof e!="object"&&typeof e!="function"&&e!=null)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,e,t,"setState")};$n.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")};function Oc(){}Oc.prototype=$n.prototype;function Bo(e,t,n){this.props=e,this.context=t,this.refs=zc,this.updater=n||Ic}var Ko=Bo.prototype=new Oc;Ko.constructor=Bo;Ac(Ko,$n.prototype);Ko.isPureReactComponent=!0;var Xa=Array.isArray,Lc=Object.prototype.hasOwnProperty,Ho={current:null},Rc={key:!0,ref:!0,__self:!0,__source:!0};function $c(e,t,n){var r,s={},o=null,a=null;if(t!=null)for(r in t.ref!==void 0&&(a=t.ref),t.key!==void 0&&(o=""+t.key),t)Lc.call(t,r)&&!Rc.hasOwnProperty(r)&&(s[r]=t[r]);var l=arguments.length-2;if(l===1)s.children=n;else if(1>>1,F=E[$];if(0>>1;$s(Le,O))Wes(Vt,Le)?(E[$]=Vt,E[We]=O,$=We):(E[$]=Le,E[ue]=O,$=ue);else if(Wes(Vt,O))E[$]=Vt,E[We]=O,$=We;else break e}}return D}function s(E,D){var O=E.sortIndex-D.sortIndex;return O!==0?O:E.id-D.id}if(typeof performance=="object"&&typeof performance.now=="function"){var o=performance;e.unstable_now=function(){return o.now()}}else{var a=Date,l=a.now();e.unstable_now=function(){return a.now()-l}}var c=[],d=[],m=1,p=null,f=3,g=!1,b=!1,w=!1,j=typeof setTimeout=="function"?setTimeout:null,x=typeof clearTimeout=="function"?clearTimeout:null,u=typeof setImmediate<"u"?setImmediate:null;typeof navigator<"u"&&navigator.scheduling!==void 0&&navigator.scheduling.isInputPending!==void 0&&navigator.scheduling.isInputPending.bind(navigator.scheduling);function h(E){for(var D=n(d);D!==null;){if(D.callback===null)r(d);else if(D.startTime<=E)r(d),D.sortIndex=D.expirationTime,t(c,D);else break;D=n(d)}}function y(E){if(w=!1,h(E),!b)if(n(c)!==null)b=!0,P(v);else{var D=n(d);D!==null&&L(y,D.startTime-E)}}function v(E,D){b=!1,w&&(w=!1,x(C),C=-1),g=!0;var O=f;try{for(h(D),p=n(c);p!==null&&(!(p.expirationTime>D)||E&&!I());){var $=p.callback;if(typeof $=="function"){p.callback=null,f=p.priorityLevel;var F=$(p.expirationTime<=D);D=e.unstable_now(),typeof F=="function"?p.callback=F:p===n(c)&&r(c),h(D)}else r(c);p=n(c)}if(p!==null)var ie=!0;else{var ue=n(d);ue!==null&&L(y,ue.startTime-D),ie=!1}return ie}finally{p=null,f=O,g=!1}}var N=!1,k=null,C=-1,z=5,A=-1;function I(){return!(e.unstable_now()-AE||125$?(E.sortIndex=O,t(d,E),n(c)===null&&E===n(d)&&(w?(x(C),C=-1):w=!0,L(y,O-$))):(E.sortIndex=F,t(c,E),b||g||(b=!0,P(v))),E},e.unstable_shouldYield=I,e.unstable_wrapCallback=function(E){var D=f;return function(){var O=f;f=D;try{return E.apply(this,arguments)}finally{f=O}}}})(Wc);Uc.exports=Wc;var Uh=Uc.exports;/**
+ * @license React
+ * react-dom.production.min.js
+ *
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */var Wh=S,Ae=Uh;function T(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Ki=Object.prototype.hasOwnProperty,Bh=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,Qa={},qa={};function Kh(e){return Ki.call(qa,e)?!0:Ki.call(Qa,e)?!1:Bh.test(e)?qa[e]=!0:(Qa[e]=!0,!1)}function Hh(e,t,n,r){if(n!==null&&n.type===0)return!1;switch(typeof t){case"function":case"symbol":return!0;case"boolean":return r?!1:n!==null?!n.acceptsBooleans:(e=e.toLowerCase().slice(0,5),e!=="data-"&&e!=="aria-");default:return!1}}function Gh(e,t,n,r){if(t===null||typeof t>"u"||Hh(e,t,n,r))return!0;if(r)return!1;if(n!==null)switch(n.type){case 3:return!t;case 4:return t===!1;case 5:return isNaN(t);case 6:return isNaN(t)||1>t}return!1}function Ne(e,t,n,r,s,o,a){this.acceptsBooleans=t===2||t===3||t===4,this.attributeName=r,this.attributeNamespace=s,this.mustUseProperty=n,this.propertyName=e,this.type=t,this.sanitizeURL=o,this.removeEmptyString=a}var pe={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach(function(e){pe[e]=new Ne(e,0,!1,e,null,!1,!1)});[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(e){var t=e[0];pe[t]=new Ne(t,1,!1,e[1],null,!1,!1)});["contentEditable","draggable","spellCheck","value"].forEach(function(e){pe[e]=new Ne(e,2,!1,e.toLowerCase(),null,!1,!1)});["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(e){pe[e]=new Ne(e,2,!1,e,null,!1,!1)});"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach(function(e){pe[e]=new Ne(e,3,!1,e.toLowerCase(),null,!1,!1)});["checked","multiple","muted","selected"].forEach(function(e){pe[e]=new Ne(e,3,!0,e,null,!1,!1)});["capture","download"].forEach(function(e){pe[e]=new Ne(e,4,!1,e,null,!1,!1)});["cols","rows","size","span"].forEach(function(e){pe[e]=new Ne(e,6,!1,e,null,!1,!1)});["rowSpan","start"].forEach(function(e){pe[e]=new Ne(e,5,!1,e.toLowerCase(),null,!1,!1)});var Jo=/[\-:]([a-z])/g;function Xo(e){return e[1].toUpperCase()}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach(function(e){var t=e.replace(Jo,Xo);pe[t]=new Ne(t,1,!1,e,null,!1,!1)});"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(e){var t=e.replace(Jo,Xo);pe[t]=new Ne(t,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)});["xml:base","xml:lang","xml:space"].forEach(function(e){var t=e.replace(Jo,Xo);pe[t]=new Ne(t,1,!1,e,"http://www.w3.org/XML/1998/namespace",!1,!1)});["tabIndex","crossOrigin"].forEach(function(e){pe[e]=new Ne(e,1,!1,e.toLowerCase(),null,!1,!1)});pe.xlinkHref=new Ne("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1);["src","href","action","formAction"].forEach(function(e){pe[e]=new Ne(e,1,!1,e.toLowerCase(),null,!0,!0)});function Yo(e,t,n,r){var s=pe.hasOwnProperty(t)?pe[t]:null;(s!==null?s.type!==0:r||!(2l||s[a]!==o[l]){var c=`
+`+s[a].replace(" at new "," at ");return e.displayName&&c.includes("")&&(c=c.replace("",e.displayName)),c}while(1<=a&&0<=l);break}}}finally{pi=!1,Error.prepareStackTrace=n}return(e=e?e.displayName||e.name:"")?qn(e):""}function Zh(e){switch(e.tag){case 5:return qn(e.type);case 16:return qn("Lazy");case 13:return qn("Suspense");case 19:return qn("SuspenseList");case 0:case 2:case 15:return e=fi(e.type,!1),e;case 11:return e=fi(e.type.render,!1),e;case 1:return e=fi(e.type,!0),e;default:return""}}function Ji(e){if(e==null)return null;if(typeof e=="function")return e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case mn:return"Fragment";case hn:return"Portal";case Hi:return"Profiler";case Qo:return"StrictMode";case Gi:return"Suspense";case Zi:return"SuspenseList"}if(typeof e=="object")switch(e.$$typeof){case Hc:return(e.displayName||"Context")+".Consumer";case Kc:return(e._context.displayName||"Context")+".Provider";case qo:var t=e.render;return e=e.displayName,e||(e=t.displayName||t.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case ea:return t=e.displayName||null,t!==null?t:Ji(e.type)||"Memo";case gt:t=e._payload,e=e._init;try{return Ji(e(t))}catch{}}return null}function Jh(e){var t=e.type;switch(e.tag){case 24:return"Cache";case 9:return(t.displayName||"Context")+".Consumer";case 10:return(t._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return e=t.render,e=e.displayName||e.name||"",t.displayName||(e!==""?"ForwardRef("+e+")":"ForwardRef");case 7:return"Fragment";case 5:return t;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return Ji(t);case 8:return t===Qo?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if(typeof t=="function")return t.displayName||t.name||null;if(typeof t=="string")return t}return null}function zt(e){switch(typeof e){case"boolean":case"number":case"string":case"undefined":return e;case"object":return e;default:return""}}function Zc(e){var t=e.type;return(e=e.nodeName)&&e.toLowerCase()==="input"&&(t==="checkbox"||t==="radio")}function Xh(e){var t=Zc(e)?"checked":"value",n=Object.getOwnPropertyDescriptor(e.constructor.prototype,t),r=""+e[t];if(!e.hasOwnProperty(t)&&typeof n<"u"&&typeof n.get=="function"&&typeof n.set=="function"){var s=n.get,o=n.set;return Object.defineProperty(e,t,{configurable:!0,get:function(){return s.call(this)},set:function(a){r=""+a,o.call(this,a)}}),Object.defineProperty(e,t,{enumerable:n.enumerable}),{getValue:function(){return r},setValue:function(a){r=""+a},stopTracking:function(){e._valueTracker=null,delete e[t]}}}}function Ur(e){e._valueTracker||(e._valueTracker=Xh(e))}function Jc(e){if(!e)return!1;var t=e._valueTracker;if(!t)return!0;var n=t.getValue(),r="";return e&&(r=Zc(e)?e.checked?"true":"false":e.value),e=r,e!==n?(t.setValue(e),!0):!1}function gs(e){if(e=e||(typeof document<"u"?document:void 0),typeof e>"u")return null;try{return e.activeElement||e.body}catch{return e.body}}function Xi(e,t){var n=t.checked;return q({},t,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:n??e._wrapperState.initialChecked})}function tl(e,t){var n=t.defaultValue==null?"":t.defaultValue,r=t.checked!=null?t.checked:t.defaultChecked;n=zt(t.value!=null?t.value:n),e._wrapperState={initialChecked:r,initialValue:n,controlled:t.type==="checkbox"||t.type==="radio"?t.checked!=null:t.value!=null}}function Xc(e,t){t=t.checked,t!=null&&Yo(e,"checked",t,!1)}function Yi(e,t){Xc(e,t);var n=zt(t.value),r=t.type;if(n!=null)r==="number"?(n===0&&e.value===""||e.value!=n)&&(e.value=""+n):e.value!==""+n&&(e.value=""+n);else if(r==="submit"||r==="reset"){e.removeAttribute("value");return}t.hasOwnProperty("value")?Qi(e,t.type,n):t.hasOwnProperty("defaultValue")&&Qi(e,t.type,zt(t.defaultValue)),t.checked==null&&t.defaultChecked!=null&&(e.defaultChecked=!!t.defaultChecked)}function nl(e,t,n){if(t.hasOwnProperty("value")||t.hasOwnProperty("defaultValue")){var r=t.type;if(!(r!=="submit"&&r!=="reset"||t.value!==void 0&&t.value!==null))return;t=""+e._wrapperState.initialValue,n||t===e.value||(e.value=t),e.defaultValue=t}n=e.name,n!==""&&(e.name=""),e.defaultChecked=!!e._wrapperState.initialChecked,n!==""&&(e.name=n)}function Qi(e,t,n){(t!=="number"||gs(e.ownerDocument)!==e)&&(n==null?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+n&&(e.defaultValue=""+n))}var er=Array.isArray;function Sn(e,t,n,r){if(e=e.options,t){t={};for(var s=0;s"+t.valueOf().toString()+"",t=Wr.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;t.firstChild;)e.appendChild(t.firstChild)}});function fr(e,t){if(t){var n=e.firstChild;if(n&&n===e.lastChild&&n.nodeType===3){n.nodeValue=t;return}}e.textContent=t}var rr={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},Yh=["Webkit","ms","Moz","O"];Object.keys(rr).forEach(function(e){Yh.forEach(function(t){t=t+e.charAt(0).toUpperCase()+e.substring(1),rr[t]=rr[e]})});function ed(e,t,n){return t==null||typeof t=="boolean"||t===""?"":n||typeof t!="number"||t===0||rr.hasOwnProperty(e)&&rr[e]?(""+t).trim():t+"px"}function td(e,t){e=e.style;for(var n in t)if(t.hasOwnProperty(n)){var r=n.indexOf("--")===0,s=ed(n,t[n],r);n==="float"&&(n="cssFloat"),r?e.setProperty(n,s):e[n]=s}}var Qh=q({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function to(e,t){if(t){if(Qh[e]&&(t.children!=null||t.dangerouslySetInnerHTML!=null))throw Error(T(137,e));if(t.dangerouslySetInnerHTML!=null){if(t.children!=null)throw Error(T(60));if(typeof t.dangerouslySetInnerHTML!="object"||!("__html"in t.dangerouslySetInnerHTML))throw Error(T(61))}if(t.style!=null&&typeof t.style!="object")throw Error(T(62))}}function no(e,t){if(e.indexOf("-")===-1)return typeof t.is=="string";switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var ro=null;function ta(e){return e=e.target||e.srcElement||window,e.correspondingUseElement&&(e=e.correspondingUseElement),e.nodeType===3?e.parentNode:e}var so=null,Cn=null,En=null;function il(e){if(e=Rr(e)){if(typeof so!="function")throw Error(T(280));var t=e.stateNode;t&&(t=Xs(t),so(e.stateNode,e.type,t))}}function nd(e){Cn?En?En.push(e):En=[e]:Cn=e}function rd(){if(Cn){var e=Cn,t=En;if(En=Cn=null,il(e),t)for(e=0;e>>=0,e===0?32:31-(cm(e)/dm|0)|0}var Br=64,Kr=4194304;function tr(e){switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return e&4194240;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return e&130023424;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return e}}function ws(e,t){var n=e.pendingLanes;if(n===0)return 0;var r=0,s=e.suspendedLanes,o=e.pingedLanes,a=n&268435455;if(a!==0){var l=a&~s;l!==0?r=tr(l):(o&=a,o!==0&&(r=tr(o)))}else a=n&~s,a!==0?r=tr(a):o!==0&&(r=tr(o));if(r===0)return 0;if(t!==0&&t!==r&&!(t&s)&&(s=r&-r,o=t&-t,s>=o||s===16&&(o&4194240)!==0))return t;if(r&4&&(r|=n&16),t=e.entangledLanes,t!==0)for(e=e.entanglements,t&=r;0n;n++)t.push(e);return t}function Or(e,t,n){e.pendingLanes|=t,t!==536870912&&(e.suspendedLanes=0,e.pingedLanes=0),e=e.eventTimes,t=31-Je(t),e[t]=n}function pm(e,t){var n=e.pendingLanes&~t;e.pendingLanes=t,e.suspendedLanes=0,e.pingedLanes=0,e.expiredLanes&=t,e.mutableReadLanes&=t,e.entangledLanes&=t,t=e.entanglements;var r=e.eventTimes;for(e=e.expirationTimes;0=ir),pl=String.fromCharCode(32),fl=!1;function Nd(e,t){switch(e){case"keyup":return Um.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function kd(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var pn=!1;function Bm(e,t){switch(e){case"compositionend":return kd(t);case"keypress":return t.which!==32?null:(fl=!0,pl);case"textInput":return e=t.data,e===pl&&fl?null:e;default:return null}}function Km(e,t){if(pn)return e==="compositionend"||!ca&&Nd(e,t)?(e=bd(),as=oa=jt=null,pn=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1