From 335064df2c349dd6f716e0cd128392cffe301d23 Mon Sep 17 00:00:00 2001 From: Claude Code Date: Mon, 29 Sep 2025 11:38:43 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=A7=B9=20Clean=20up=20project=20structure?= =?UTF-8?q?=20and=20restore=20original=20interface?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove unnecessary backend/, frontend/, saas-automation-platform/ folders - Remove duplicate server files (server-new.js, server-old.js) - Remove old archive files (*.tar.gz) - Remove outdated documentation and deploy scripts - Maintain only essential project files for SaaS platform - Original Russian interface is now primary interface 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- DEMO.md | 105 - DEPLOY.md | 148 - VPS-DEPLOY.md | 236 - backend/.env.example | 29 - backend/Dockerfile | 21 - backend/Dockerfile.dev | 18 - backend/package-lock.json | 1995 ----- backend/package.json | 38 - backend/src/controllers/adminController.ts | 312 - backend/src/controllers/authController.ts | 173 - backend/src/controllers/billingController.ts | 337 - backend/src/controllers/chatController.ts | 91 - .../src/controllers/integrationController.ts | 107 - backend/src/controllers/logController.ts | 79 - backend/src/controllers/templateController.ts | 198 - backend/src/controllers/webhookController.ts | 167 - backend/src/controllers/workflowController.ts | 456 -- backend/src/db/connection.ts | 20 - backend/src/index.ts | 713 -- backend/src/index_backup.ts | 28 - backend/src/index_full.ts | 45 - backend/src/middleware/auth.ts | 36 - backend/src/routes/admin.ts | 27 - backend/src/routes/auth.ts | 10 - backend/src/routes/billing.ts | 28 - backend/src/routes/chat.ts | 11 - backend/src/routes/integrations.ts | 12 - backend/src/routes/logs.ts | 11 - backend/src/routes/templates.ts | 10 - backend/src/routes/webhooks.ts | 16 - backend/src/routes/workflows.ts | 34 - backend/src/services/n8nService.ts | 226 - backend/src/types/index.ts | 35 - backend/src/utils/auth.ts | 26 - backend/src/utils/db.ts | 18 - backend/tsconfig.json | 16 - deploy.sh | 96 - frontend/.gitignore | 41 - frontend/Dockerfile | 21 - frontend/Dockerfile.dev | 18 - frontend/README.md | 36 - frontend/eslint.config.mjs | 25 - frontend/next.config.ts | 7 - frontend/package-lock.json | 6420 ----------------- frontend/package.json | 31 - frontend/postcss.config.mjs | 5 - frontend/src/app/admin/page.tsx | 505 -- frontend/src/app/billing/page.tsx | 474 -- frontend/src/app/chat/page.tsx | 200 - frontend/src/app/dashboard/page.tsx | 317 - frontend/src/app/favicon.ico | Bin 25931 -> 0 bytes frontend/src/app/globals.css | 128 - frontend/src/app/integrations/page.tsx | 334 - frontend/src/app/layout.tsx | 38 - frontend/src/app/login/page.tsx | 206 - frontend/src/app/marketplace/page.tsx | 442 -- frontend/src/app/page.tsx | 250 - frontend/src/app/signup/page.tsx | 109 - frontend/src/app/workflows/page.tsx | 396 - frontend/src/components/ClientProvider.tsx | 7 - frontend/src/components/Layout.tsx | 176 - frontend/src/hooks/useAuth.tsx | 87 - frontend/src/lib/api.ts | 32 - frontend/src/types/index.ts | 75 - frontend/tsconfig.json | 27 - server-new.js | 334 - server-old.js | 17 - 67 files changed, 16686 deletions(-) delete mode 100644 DEMO.md delete mode 100644 DEPLOY.md delete mode 100644 VPS-DEPLOY.md delete mode 100644 backend/.env.example delete mode 100644 backend/Dockerfile delete mode 100644 backend/Dockerfile.dev delete mode 100644 backend/package-lock.json delete mode 100644 backend/package.json delete mode 100644 backend/src/controllers/adminController.ts delete mode 100644 backend/src/controllers/authController.ts delete mode 100644 backend/src/controllers/billingController.ts delete mode 100644 backend/src/controllers/chatController.ts delete mode 100644 backend/src/controllers/integrationController.ts delete mode 100644 backend/src/controllers/logController.ts delete mode 100644 backend/src/controllers/templateController.ts delete mode 100644 backend/src/controllers/webhookController.ts delete mode 100644 backend/src/controllers/workflowController.ts delete mode 100644 backend/src/db/connection.ts delete mode 100644 backend/src/index.ts delete mode 100644 backend/src/index_backup.ts delete mode 100644 backend/src/index_full.ts delete mode 100644 backend/src/middleware/auth.ts delete mode 100644 backend/src/routes/admin.ts delete mode 100644 backend/src/routes/auth.ts delete mode 100644 backend/src/routes/billing.ts delete mode 100644 backend/src/routes/chat.ts delete mode 100644 backend/src/routes/integrations.ts delete mode 100644 backend/src/routes/logs.ts delete mode 100644 backend/src/routes/templates.ts delete mode 100644 backend/src/routes/webhooks.ts delete mode 100644 backend/src/routes/workflows.ts delete mode 100644 backend/src/services/n8nService.ts delete mode 100644 backend/src/types/index.ts delete mode 100644 backend/src/utils/auth.ts delete mode 100644 backend/src/utils/db.ts delete mode 100644 backend/tsconfig.json delete mode 100755 deploy.sh delete mode 100644 frontend/.gitignore delete mode 100644 frontend/Dockerfile delete mode 100644 frontend/Dockerfile.dev delete mode 100644 frontend/README.md delete mode 100644 frontend/eslint.config.mjs delete mode 100644 frontend/next.config.ts delete mode 100644 frontend/package-lock.json delete mode 100644 frontend/package.json delete mode 100644 frontend/postcss.config.mjs delete mode 100644 frontend/src/app/admin/page.tsx delete mode 100644 frontend/src/app/billing/page.tsx delete mode 100644 frontend/src/app/chat/page.tsx delete mode 100644 frontend/src/app/dashboard/page.tsx delete mode 100644 frontend/src/app/favicon.ico delete mode 100644 frontend/src/app/globals.css delete mode 100644 frontend/src/app/integrations/page.tsx delete mode 100644 frontend/src/app/layout.tsx delete mode 100644 frontend/src/app/login/page.tsx delete mode 100644 frontend/src/app/marketplace/page.tsx delete mode 100644 frontend/src/app/page.tsx delete mode 100644 frontend/src/app/signup/page.tsx delete mode 100644 frontend/src/app/workflows/page.tsx delete mode 100644 frontend/src/components/ClientProvider.tsx delete mode 100644 frontend/src/components/Layout.tsx delete mode 100644 frontend/src/hooks/useAuth.tsx delete mode 100644 frontend/src/lib/api.ts delete mode 100644 frontend/src/types/index.ts delete mode 100644 frontend/tsconfig.json delete mode 100644 server-new.js delete mode 100644 server-old.js diff --git a/DEMO.md b/DEMO.md deleted file mode 100644 index 9d596be..0000000 --- a/DEMO.md +++ /dev/null @@ -1,105 +0,0 @@ -# 🚀 Aimpress AutomationHub - Demo Guide - -## Что показать коллегам - -### 📱 **Главная страница** - `/` -- Современный landing page с градиентами -- Responsive дизайн в стиле n8n -- Call-to-action кнопки - -### 🔐 **Авторизация** - `/login` -- **Админ логин:** - - Email: `info@ai-impress.com` - - Password: `admin123` -- **Signup** - регистрация новых пользователей - -### 📊 **Admin Panel** - `/admin` -- **Analytics Dashboard** с метриками: - - 156 пользователей (120 free, 28 pro, 6 enterprise) - - 342 workflows, 12,847 выполнений - - $18,750 revenue -- **User Management** - управление пользователями и лицензиями -- **Real-time данные** и графики - -### 🛍️ **Template Marketplace** - `/marketplace` -- **6 готовых шаблонов** с эмодзи иконками: - - 🔗 Telegram to Slack Bridge - - 📧 Gmail to Teams Notifications - - 🎧 Customer Support Automation - - 📱 Social Media Content Sync - - 🛒 E-commerce Order Processing - - ☁️ Data Backup & Sync -- **Рейтинги, категории, фильтры** -- **Функция установки шаблонов** - -### 🔗 **Integrations** - `/integrations` -- **10 популярных интеграций:** - - Gmail, Slack, Telegram, Microsoft Teams - - Instagram, LinkedIn, Shopify, Zoho CRM - - Calendly, Webhooks -- **Красивые карточки** с градиентами -- **Mock подключения** к сервисам - -### 💳 **Billing** - `/billing` -- **3 тарифных плана:** - - Free (0£/month) - - Pro (£150/month) - - Enterprise (contact sales) -- **Usage tracking** и статистика - -### 🔧 **Dashboard** - `/dashboard` -- **Workflow management** -- **Statistics overview** -- **Quick actions** - -## 🔑 **Key Features для демо:** - -1. **🎨 Визуальный дизайн** - современные градиенты, анимации, hover-эффекты -2. **👨‍💼 Admin функции** - управление пользователями, аналитика, лицензии -3. **🛍️ Marketplace** - готовые шаблоны автоматизации -4. **🔗 Integrations** - подключение к популярным сервисам -5. **📱 Responsive** - работает на всех устройствах -6. **⚡ Performance** - быстрая загрузка, плавные анимации - -## 🚀 **Как запустить:** - -```bash -# В директории проекта -docker-compose up -d - -# Проверить что все запущено -docker-compose ps -``` - -**Доступ:** -- Frontend: http://localhost:3000 -- Backend API: http://localhost:3001 -- Database: PostgreSQL на порту 5432 -- N8n: http://localhost:5678 - -## 📋 **Что показать в первую очередь:** - -1. **Landing page** - красивый дизайн -2. **Admin login** - войти как админ -3. **Admin Analytics** - впечатляющая статистика -4. **Template Marketplace** - готовые шаблоны -5. **Integrations** - список подключений -6. **User Management** - назначение лицензий - -## 💡 **Фишки для демо:** - -- **Эмодзи иконки** делают интерфейс дружелюбным -- **Градиенты** создают современный вид -- **Анимации** при hover и загрузке -- **Responsive дизайн** работает на мобильных -- **Mock данные** выглядят реалистично -- **Функциональные кнопки** с feedback - -## 🔧 **Технический стек:** - -- **Frontend:** Next.js 15, TypeScript, Tailwind CSS -- **Backend:** Node.js, Express, TypeScript -- **Database:** PostgreSQL -- **Container:** Docker Compose -- **Integration:** N8n workflow automation -- **Design:** n8n-inspired modern UI/UX \ No newline at end of file diff --git a/DEPLOY.md b/DEPLOY.md deleted file mode 100644 index c524225..0000000 --- a/DEPLOY.md +++ /dev/null @@ -1,148 +0,0 @@ -# 🚀 Деплой Click Counter на VPS - -## Подготовка VPS - -Убедитесь что на VPS установлены: -```bash -# Docker -curl -fsSL https://get.docker.com -o get-docker.sh -sudo sh get-docker.sh - -# Docker Compose -sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose -sudo chmod +x /usr/local/bin/docker-compose -``` - -## Автоматический деплой - -### Простой способ -```bash -./deploy.sh YOUR_VPS_IP root -``` - -### С пользователем -```bash -./deploy.sh 192.168.1.100 ubuntu -``` - -## Ручной деплой - -### 1. Создание архива -```bash -tar --exclude='.git' --exclude='node_modules' --exclude='*.log' --exclude='.DS_Store' --exclude='saas-*' --exclude='*.tar.gz' -czf click-counter-deploy.tar.gz Dockerfile docker-compose.yml .dockerignore package.json package-lock.json server.js public/ -``` - -### 2. Загрузка на VPS -```bash -scp click-counter-deploy.tar.gz root@YOUR_VPS_IP:/tmp/ -``` - -### 3. Деплой на VPS -```bash -ssh root@YOUR_VPS_IP -mkdir -p /opt/click-counter -cd /opt/click-counter -tar -xzf /tmp/click-counter-deploy.tar.gz -docker-compose down || true -docker-compose build --no-cache -docker-compose up -d -``` - -## Управление приложением - -### Проверить статус -```bash -ssh root@YOUR_VPS_IP 'cd /opt/click-counter && docker-compose ps' -``` - -### Посмотреть логи -```bash -ssh root@YOUR_VPS_IP 'cd /opt/click-counter && docker-compose logs -f' -``` - -### Перезапустить -```bash -ssh root@YOUR_VPS_IP 'cd /opt/click-counter && docker-compose restart' -``` - -### Остановить -```bash -ssh root@YOUR_VPS_IP 'cd /opt/click-counter && docker-compose down' -``` - -### Обновить приложение -```bash -./deploy.sh YOUR_VPS_IP root -``` - -## Мониторинг - -### Health check -```bash -curl http://YOUR_VPS_IP:3000/health -``` - -### Использование ресурсов -```bash -ssh root@YOUR_VPS_IP 'docker stats click-counter --no-stream' -``` - -## Настройки - -### Изменить порт -В `docker-compose.yml` измените: -```yaml -ports: - - "8080:3000" # Вместо 3000:3000 -``` - -### Ограничения памяти -В `docker-compose.yml` настройте: -```yaml -deploy: - resources: - limits: - memory: 256M # Увеличить лимит -``` - -## Размер образа - -Оптимизации для минимального размера: -- ✅ Alpine Linux (базовый образ ~5MB) -- ✅ Multi-stage build -- ✅ Минификация статики -- ✅ .dockerignore -- ✅ Очистка кэша npm - -Ожидаемый размер итогового образа: ~50-70MB - -## Безопасность - -- ✅ Непривилегированный пользователь -- ✅ Read-only файловая система где возможно -- ✅ Ограничения ресурсов -- ✅ Health checks -- ✅ Логирование с ротацией - -## Troubleshooting - -### Контейнер не запускается -```bash -ssh root@YOUR_VPS_IP 'cd /opt/click-counter && docker-compose logs' -``` - -### Порт занят -```bash -ssh root@YOUR_VPS_IP 'netstat -tlnp | grep :3000' -``` - -### Мало места -```bash -ssh root@YOUR_VPS_IP 'docker system prune -af' -``` - -### Проблемы с Docker -```bash -ssh root@YOUR_VPS_IP 'systemctl status docker' -ssh root@YOUR_VPS_IP 'systemctl restart docker' -``` \ No newline at end of file diff --git a/VPS-DEPLOY.md b/VPS-DEPLOY.md deleted file mode 100644 index db52a81..0000000 --- a/VPS-DEPLOY.md +++ /dev/null @@ -1,236 +0,0 @@ -# 🚀 VPS Deployment - Aimpress AutomationHub - -## 🌐 **Развертывание на VPS сервере 128.140.8.206** - -### Шаг 1: Подключение к серверу -```bash -# Подключиться к VPS -ssh root@128.140.8.206 -# или -ssh your-username@128.140.8.206 -``` - -### Шаг 2: Установка Docker (если не установлен) -```bash -# Обновить пакеты -apt update && apt upgrade -y - -# Установить Docker -curl -fsSL https://get.docker.com -o get-docker.sh -sh get-docker.sh - -# Установить Docker Compose -curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose -chmod +x /usr/local/bin/docker-compose - -# Проверить установку -docker --version -docker-compose --version -``` - -### Шаг 3: Клонирование проекта -```bash -# Установить Git (если не установлен) -apt install git -y - -# Клонировать репозиторий -git clone https://github.com/SamoilenkoVadym/SaaS.git -cd SaaS -``` - -### Шаг 4: Конфигурация для production -```bash -# Создать production docker-compose -cp docker-compose.yml docker-compose.prod.yml - -# Изменить порты для внешнего доступа -sed -i 's/- "3000:3000"/- "80:3000"/' docker-compose.prod.yml -sed -i 's/- "3001:3001"/- "3001:3001"/' docker-compose.prod.yml -``` - -### Шаг 5: Настройка переменных окружения -```bash -# Backend environment -cat > backend/.env << EOF -PORT=3001 -DB_HOST=postgres -DB_PORT=5432 -DB_NAME=saas_automation -DB_USER=postgres -DB_PASSWORD=secure_production_password_123 -JWT_SECRET=your_super_secret_jwt_key_production_123 -NODE_ENV=production -EOF - -# Frontend environment -cat > frontend/.env.local << EOF -NEXT_PUBLIC_API_URL=http://128.140.8.206:3001 -EOF -``` - -### Шаг 6: Запуск приложения -```bash -# Запустить все сервисы -docker-compose -f docker-compose.prod.yml up -d - -# Проверить статус -docker-compose -f docker-compose.prod.yml ps - -# Посмотреть логи -docker-compose -f docker-compose.prod.yml logs -f -``` - -### Шаг 7: Настройка firewall (опционально) -```bash -# Открыть нужные порты -ufw allow 80 -ufw allow 3001 -ufw allow 22 -ufw --force enable -``` - -## 🌐 **Доступ к приложению** - -После успешного развертывания приложение будет доступно: - -- **🌐 Главная страница:** http://128.140.8.206 -- **👨‍💼 Admin Panel:** http://128.140.8.206/admin -- **🛍️ Marketplace:** http://128.140.8.206/marketplace -- **🔗 Integrations:** http://128.140.8.206/integrations -- **🔧 Backend API:** http://128.140.8.206:3001 - -### 🔐 **Тестовые аккаунты** -**Admin:** -- Email: `info@ai-impress.com` -- Password: `admin123` - -## 📊 **Мониторинг и обслуживание** - -### Проверка статуса -```bash -# Проверить работающие контейнеры -docker ps - -# Проверить логи -docker-compose -f docker-compose.prod.yml logs frontend -docker-compose -f docker-compose.prod.yml logs backend -docker-compose -f docker-compose.prod.yml logs postgres -``` - -### Обновление приложения -```bash -# Остановить контейнеры -docker-compose -f docker-compose.prod.yml down - -# Обновить код -git pull origin main - -# Пересобрать и запустить -docker-compose -f docker-compose.prod.yml up -d --build -``` - -### Резервное копирование базы данных -```bash -# Создать backup -docker-compose -f docker-compose.prod.yml exec postgres pg_dump -U postgres saas_automation > backup_$(date +%Y%m%d).sql - -# Восстановить из backup -docker-compose -f docker-compose.prod.yml exec -T postgres psql -U postgres saas_automation < backup_20241228.sql -``` - -## 🔒 **Безопасность для production** - -### SSL сертификат (рекомендуется) -```bash -# Установить Certbot -apt install certbot -y - -# Если у вас есть домен, получить SSL сертификат -# certbot --nginx -d yourdomain.com - -# Настроить автообновление -crontab -e -# Добавить: 0 12 * * * /usr/bin/certbot renew --quiet -``` - -### Изменить пароли по умолчанию -```bash -# Изменить пароль базы данных -# Обновить docker-compose.prod.yml и backend/.env -# Изменить JWT_SECRET на уникальный ключ -``` - -## 🚨 **Troubleshooting** - -### Проблема: Контейнеры не запускаются -```bash -# Проверить логи -docker-compose -f docker-compose.prod.yml logs - -# Очистить старые образы -docker system prune -a - -# Пересобрать -docker-compose -f docker-compose.prod.yml up -d --build -``` - -### Проблема: База данных не подключается -```bash -# Проверить статус PostgreSQL -docker-compose -f docker-compose.prod.yml exec postgres pg_isready - -# Подключиться к базе данных -docker-compose -f docker-compose.prod.yml exec postgres psql -U postgres saas_automation -``` - -### Проблема: Frontend не загружается -```bash -# Проверить переменные окружения -cat frontend/.env.local - -# Убедиться что API_URL указывает на правильный адрес -# Должен быть: NEXT_PUBLIC_API_URL=http://128.140.8.206:3001 -``` - -## 📞 **Поддержка** - -При возникновении проблем: -1. Проверить логи: `docker-compose logs` -2. Проверить статус: `docker-compose ps` -3. Перезапустить: `docker-compose restart` -4. Связаться с командой: info@ai-impress.com - ---- - -## 🎯 **Быстрая команда для полного развертывания** - -```bash -# Скопировать и выполнить весь блок -ssh root@128.140.8.206 ' -apt update && apt upgrade -y && -curl -fsSL https://get.docker.com -o get-docker.sh && sh get-docker.sh && -curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose && -chmod +x /usr/local/bin/docker-compose && -apt install git -y && -git clone https://github.com/SamoilenkoVadym/SaaS.git && -cd SaaS && -cp docker-compose.yml docker-compose.prod.yml && -sed -i "s/- \"3000:3000\"/- \"80:3000\"/" docker-compose.prod.yml && -cat > backend/.env << EOF -PORT=3001 -DB_HOST=postgres -DB_PORT=5432 -DB_NAME=saas_automation -DB_USER=postgres -DB_PASSWORD=secure_production_password_123 -JWT_SECRET=your_super_secret_jwt_key_production_123 -NODE_ENV=production -EOF -cat > frontend/.env.local << EOF -NEXT_PUBLIC_API_URL=http://128.140.8.206:3001 -EOF -docker-compose -f docker-compose.prod.yml up -d -' -``` - -После выполнения команды приложение будет доступно по адресу: **http://128.140.8.206** \ No newline at end of file diff --git a/backend/.env.example b/backend/.env.example deleted file mode 100644 index 20f1a06..0000000 --- a/backend/.env.example +++ /dev/null @@ -1,29 +0,0 @@ -PORT=3001 -NODE_ENV=development - -# Database -DB_HOST=localhost -DB_PORT=5432 -DB_NAME=saas_automation -DB_USER=postgres -DB_PASSWORD=password - -# JWT -JWT_SECRET=your_super_secret_jwt_key_change_this -JWT_EXPIRES_IN=24h - -# Email (for password reset) -SMTP_HOST=smtp.gmail.com -SMTP_PORT=587 -SMTP_USER=your_email@gmail.com -SMTP_PASSWORD=your_app_password - -# OAuth Secrets (add as needed) -GOOGLE_CLIENT_ID=your_google_client_id -GOOGLE_CLIENT_SECRET=your_google_client_secret -INSTAGRAM_CLIENT_ID=your_instagram_client_id -INSTAGRAM_CLIENT_SECRET=your_instagram_client_secret - -# n8n Integration -N8N_BASE_URL=https://bot.ai-impress.com -N8N_API_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1OWQyN2Q0ZS1jNTU3LTQxMDUtYjZmMy05Y2JmM2U5MzU1NWUiLCJpc3MiOiJuOG4iLCJhdWQiOiJwdWJsaWMtYXBpIiwiaWF0IjoxNzU5MDc1NDI4fQ.HCnDOPdq8GcphuPpz1o9871VOLbpMvd7m8C47e2Kq50 \ No newline at end of file diff --git a/backend/Dockerfile b/backend/Dockerfile deleted file mode 100644 index cfd1dbf..0000000 --- a/backend/Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -FROM node:18-alpine - -WORKDIR /app - -# Copy package.json and package-lock.json (if available) -COPY package*.json ./ - -# Install dependencies -RUN npm ci --only=production - -# Copy source code -COPY . . - -# Build the application -RUN npm run build - -# Expose port -EXPOSE 3001 - -# Start the application -CMD ["npm", "start"] \ No newline at end of file diff --git a/backend/Dockerfile.dev b/backend/Dockerfile.dev deleted file mode 100644 index aedfadb..0000000 --- a/backend/Dockerfile.dev +++ /dev/null @@ -1,18 +0,0 @@ -FROM node:18-alpine - -WORKDIR /app - -# Copy package.json and package-lock.json -COPY package*.json ./ - -# Install all dependencies (including dev dependencies) -RUN npm install - -# Copy source code -COPY . . - -# Expose port -EXPOSE 3001 - -# Start the application in development mode -CMD ["npm", "run", "dev"] \ No newline at end of file diff --git a/backend/package-lock.json b/backend/package-lock.json deleted file mode 100644 index 7020480..0000000 --- a/backend/package-lock.json +++ /dev/null @@ -1,1995 +0,0 @@ -{ - "name": "backend", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "backend", - "version": "1.0.0", - "license": "ISC", - "dependencies": { - "axios": "^1.12.2", - "bcryptjs": "^3.0.2", - "cors": "^2.8.5", - "dotenv": "^17.2.2", - "express": "^5.1.0", - "helmet": "^8.1.0", - "jsonwebtoken": "^9.0.2", - "nodemailer": "^7.0.6", - "pg": "^8.16.3" - }, - "devDependencies": { - "@types/bcryptjs": "^2.4.6", - "@types/cors": "^2.8.19", - "@types/express": "^5.0.3", - "@types/jsonwebtoken": "^9.0.10", - "@types/node": "^24.5.2", - "nodemon": "^3.1.10", - "ts-node": "^10.9.2", - "typescript": "^5.9.2" - } - }, - "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/@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.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==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.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/bcryptjs": { - "version": "2.4.6", - "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.6.tgz", - "integrity": "sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==", - "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/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": "5.0.3", - "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.3.tgz", - "integrity": "sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^5.0.0", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.7.tgz", - "integrity": "sha512-R+33OsgWw7rOhD1emjU7dzCDHucJrgJXMA5PYCzJxVil0dsyx5iBEPHqpPfiKNJQb7lZ1vxwoLR4Z87bBUpeGQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "node_modules/@types/http-errors": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", - "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/jsonwebtoken": { - "version": "9.0.10", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz", - "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/ms": "*", - "@types/node": "*" - } - }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/ms": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", - "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "24.5.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.5.2.tgz", - "integrity": "sha512-FYxk1I7wPv3K2XBaoyH2cTnocQEu8AOZ60hPbsyukMPLv5/5qr7V1i8PLHdl6Zf87I+xZXFvPCXYjiTFq+YSDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~7.12.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/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/accepts": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", - "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", - "license": "MIT", - "dependencies": { - "mime-types": "^3.0.0", - "negotiator": "^1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "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/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/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.12.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz", - "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.4", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/bcryptjs": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-3.0.2.tgz", - "integrity": "sha512-k38b3XOZKv60C4E2hVsXTolJWfkGRMbILBIe2IBITXciy5bOsTKot5kDrf3ZfufQtQOUN5mXceUEpU1rTl9Uog==", - "license": "BSD-3-Clause", - "bin": { - "bcrypt": "bin/bcrypt" - } - }, - "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": "2.2.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", - "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", - "license": "MIT", - "dependencies": { - "bytes": "^3.1.2", - "content-type": "^1.0.5", - "debug": "^4.4.0", - "http-errors": "^2.0.0", - "iconv-lite": "^0.6.3", - "on-finished": "^2.4.1", - "qs": "^6.14.0", - "raw-body": "^3.0.0", - "type-is": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/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/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/call-bind-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/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/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": "1.0.0", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", - "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", - "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", - "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", - "license": "MIT", - "engines": { - "node": ">=6.6.0" - } - }, - "node_modules/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/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/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "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": "17.2.2", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.2.tgz", - "integrity": "sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q==", - "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/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/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/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": "5.1.0", - "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", - "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", - "license": "MIT", - "dependencies": { - "accepts": "^2.0.0", - "body-parser": "^2.2.0", - "content-disposition": "^1.0.0", - "content-type": "^1.0.5", - "cookie": "^0.7.1", - "cookie-signature": "^1.2.1", - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "finalhandler": "^2.1.0", - "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "merge-descriptors": "^2.0.0", - "mime-types": "^3.0.0", - "on-finished": "^2.4.1", - "once": "^1.4.0", - "parseurl": "^1.3.3", - "proxy-addr": "^2.0.7", - "qs": "^6.14.0", - "range-parser": "^1.2.1", - "router": "^2.2.0", - "send": "^1.1.0", - "serve-static": "^2.2.0", - "statuses": "^2.0.1", - "type-is": "^2.0.1", - "vary": "^1.1.2" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/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": "2.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", - "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "on-finished": "^2.4.1", - "parseurl": "^1.3.3", - "statuses": "^2.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/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/form-data": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/form-data/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/form-data/node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", - "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/helmet": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/helmet/-/helmet-8.1.0.tgz", - "integrity": "sha512-jOiHyAZsmnr8LqoPGmCjYAaiuWwjAPLgY8ZX2XrmHawt99/u1y6RgrZMTeoPfpUbV96HOalYgz1qzkRbw54Pmg==", - "license": "MIT", - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-errors/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", - "dev": true, - "license": "ISC" - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/is-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-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-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-promise": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", - "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", - "license": "MIT" - }, - "node_modules/jsonwebtoken": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", - "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", - "license": "MIT", - "dependencies": { - "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=12", - "npm": ">=6" - } - }, - "node_modules/jwa": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", - "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", - "license": "MIT", - "dependencies": { - "buffer-equal-constant-time": "^1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "license": "MIT", - "dependencies": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/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/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true, - "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": "1.1.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", - "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/merge-descriptors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", - "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", - "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", - "license": "MIT", - "dependencies": { - "mime-db": "^1.54.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/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/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/negotiator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/nodemailer": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.6.tgz", - "integrity": "sha512-F44uVzgwo49xboqbFgBGkRaiMgtoBrBEWCVincJPK9+S9Adkzt/wXCLKbf7dxucmxfTI5gHGB+bEmdyzN6QKjw==", - "license": "MIT-0", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/nodemon": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.10.tgz", - "integrity": "sha512-WDjw3pJ0/0jMFmyNDp3gvY2YizjLmmOUQo6DEBY+JgdvW/yQ9mEeSw6H5ythl5Ny2ytb7f9C2nIbjSxMNzbJXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chokidar": "^3.5.2", - "debug": "^4", - "ignore-by-default": "^1.0.1", - "minimatch": "^3.1.2", - "pstree.remy": "^1.1.8", - "semver": "^7.5.3", - "simple-update-notifier": "^2.0.0", - "supports-color": "^5.5.0", - "touch": "^3.1.0", - "undefsafe": "^2.0.5" - }, - "bin": { - "nodemon": "bin/nodemon.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nodemon" - } - }, - "node_modules/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/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/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-to-regexp": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", - "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "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==", - "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/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "license": "MIT" - }, - "node_modules/pstree.remy": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", - "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", - "dev": true, - "license": "MIT" - }, - "node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.1.tgz", - "integrity": "sha512-9G8cA+tuMS75+6G/TzW8OtLzmBDMo8p1JRxN5AZ+LAp8uxGA8V8GZm4GQ4/N5QNQEnLmg6SS7wyuSmbKepiKqA==", - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.7.0", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/raw-body/node_modules/iconv-lite": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", - "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/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/router": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", - "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "depd": "^2.0.0", - "is-promise": "^4.0.0", - "parseurl": "^1.3.3", - "path-to-regexp": "^8.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/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": "1.2.0", - "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", - "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", - "license": "MIT", - "dependencies": { - "debug": "^4.3.5", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "mime-types": "^3.0.1", - "ms": "^2.1.3", - "on-finished": "^2.4.1", - "range-parser": "^1.2.1", - "statuses": "^2.0.1" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/serve-static": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", - "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", - "license": "MIT", - "dependencies": { - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "parseurl": "^1.3.3", - "send": "^1.2.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/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/simple-update-notifier": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", - "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/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.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/touch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", - "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", - "dev": true, - "license": "ISC", - "bin": { - "nodetouch": "bin/nodetouch.js" - } - }, - "node_modules/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/type-is": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", - "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", - "license": "MIT", - "dependencies": { - "content-type": "^1.0.5", - "media-typer": "^1.1.0", - "mime-types": "^3.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typescript": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", - "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/undefsafe": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", - "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", - "dev": true, - "license": "MIT" - }, - "node_modules/undici-types": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.12.0.tgz", - "integrity": "sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ==", - "dev": true, - "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/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/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/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/package.json b/backend/package.json deleted file mode 100644 index 9a52b45..0000000 --- a/backend/package.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "name": "backend", - "version": "1.0.0", - "description": "", - "main": "dist/index.js", - "scripts": { - "dev": "nodemon src/index.ts", - "build": "tsc", - "start": "node dist/index.js", - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [], - "author": "", - "license": "ISC", - "type": "commonjs", - "dependencies": { - "axios": "^1.12.2", - "bcryptjs": "^3.0.2", - "cors": "^2.8.5", - "dotenv": "^17.2.2", - "express": "^5.1.0", - "helmet": "^8.1.0", - "jsonwebtoken": "^9.0.2", - "nodemailer": "^7.0.6", - "pg": "^8.16.3" - }, - "devDependencies": { - "@types/bcryptjs": "^2.4.6", - "@types/cors": "^2.8.19", - "@types/express": "^5.0.3", - "@types/jsonwebtoken": "^9.0.10", - "@types/node": "^24.5.2", - "@types/pg": "^8.11.10", - "nodemon": "^3.1.10", - "ts-node": "^10.9.2", - "typescript": "^5.9.2" - } -} diff --git a/backend/src/controllers/adminController.ts b/backend/src/controllers/adminController.ts deleted file mode 100644 index 362e391..0000000 --- a/backend/src/controllers/adminController.ts +++ /dev/null @@ -1,312 +0,0 @@ -import { Request, Response } from 'express'; -import { pool } from '../db/connection'; -import { AuthRequest } from '../middleware/auth'; - -export const getAnalytics = async (req: AuthRequest, res: Response) => { - try { - // Check if user is admin - if (req.user.role !== 'admin') { - return res.status(403).json({ error: 'Access denied. Admin role required.' }); - } - - // Get user statistics - const userStatsQuery = ` - SELECT - COUNT(*) as total_users, - COUNT(CASE WHEN subscription_plan = 'free' THEN 1 END) as free_users, - COUNT(CASE WHEN subscription_plan = 'pro' THEN 1 END) as pro_users, - COUNT(CASE WHEN subscription_plan = 'enterprise' THEN 1 END) as enterprise_users, - COUNT(CASE WHEN is_verified = true THEN 1 END) as verified_users, - COUNT(CASE WHEN last_login_at > NOW() - INTERVAL '7 days' THEN 1 END) as active_last_7_days, - COUNT(CASE WHEN created_at > NOW() - INTERVAL '30 days' THEN 1 END) as new_last_30_days - FROM users - `; - - // Get workflow statistics - const workflowStatsQuery = ` - SELECT - COUNT(*) as total_workflows, - COUNT(CASE WHEN is_active = true THEN 1 END) as active_workflows, - COUNT(CASE WHEN created_at > NOW() - INTERVAL '30 days' THEN 1 END) as new_workflows_30_days, - AVG(CASE WHEN is_active = true THEN 1.0 ELSE 0.0 END) * 100 as activation_rate - FROM workflows - `; - - // Get execution statistics - const executionStatsQuery = ` - SELECT - COUNT(*) as total_executions, - COUNT(CASE WHEN status = 'success' THEN 1 END) as successful_executions, - COUNT(CASE WHEN created_at > NOW() - INTERVAL '24 hours' THEN 1 END) as executions_24h, - COUNT(CASE WHEN created_at > NOW() - INTERVAL '7 days' THEN 1 END) as executions_7d - FROM workflow_executions - `; - - // Get revenue statistics - const revenueStatsQuery = ` - SELECT - SUM(amount) as total_revenue, - SUM(CASE WHEN created_at > NOW() - INTERVAL '30 days' THEN amount ELSE 0 END) as revenue_30_days, - COUNT(CASE WHEN payment_status = 'completed' THEN 1 END) as successful_payments, - AVG(amount) as average_order_value - FROM subscription_history - WHERE payment_status = 'completed' - `; - - // Get integration statistics - const integrationStatsQuery = ` - SELECT - COUNT(*) as total_integrations, - COUNT(CASE WHEN is_active = true THEN 1 END) as active_integrations, - provider, - COUNT(*) as count - FROM integrations - GROUP BY provider - `; - - // Get recent activity - const recentActivityQuery = ` - SELECT - action, - resource_type, - created_at, - u.email as user_email - FROM audit_logs a - LEFT JOIN users u ON a.user_id = u.id - ORDER BY created_at DESC - LIMIT 20 - `; - - // Get top users by workflows - const topUsersQuery = ` - SELECT - u.email, - u.first_name, - u.last_name, - u.subscription_plan, - COUNT(w.id) as workflow_count, - u.last_login_at - FROM users u - LEFT JOIN workflows w ON u.id = w.user_id - GROUP BY u.id, u.email, u.first_name, u.last_name, u.subscription_plan, u.last_login_at - ORDER BY workflow_count DESC - LIMIT 10 - `; - - // Execute all queries - const [ - userStats, - workflowStats, - executionStats, - revenueStats, - integrationStats, - recentActivity, - topUsers - ] = await Promise.all([ - pool.query(userStatsQuery), - pool.query(workflowStatsQuery), - pool.query(executionStatsQuery), - pool.query(revenueStatsQuery), - pool.query(integrationStatsQuery), - pool.query(recentActivityQuery), - pool.query(topUsersQuery) - ]); - - // Get daily registrations for the last 30 days - const dailyRegistrationsQuery = ` - SELECT - DATE(created_at) as date, - COUNT(*) as registrations - FROM users - WHERE created_at > NOW() - INTERVAL '30 days' - GROUP BY DATE(created_at) - ORDER BY date - `; - - const dailyRegistrations = await pool.query(dailyRegistrationsQuery); - - // Get workflow executions trend - const executionTrendQuery = ` - SELECT - DATE(created_at) as date, - COUNT(*) as executions, - COUNT(CASE WHEN status = 'success' THEN 1 END) as successful - FROM workflow_executions - WHERE created_at > NOW() - INTERVAL '30 days' - GROUP BY DATE(created_at) - ORDER BY date - `; - - const executionTrend = await pool.query(executionTrendQuery); - - res.json({ - userStats: userStats.rows[0], - workflowStats: workflowStats.rows[0], - executionStats: executionStats.rows[0], - revenueStats: revenueStats.rows[0], - integrationStats: integrationStats.rows, - recentActivity: recentActivity.rows, - topUsers: topUsers.rows, - dailyRegistrations: dailyRegistrations.rows, - executionTrend: executionTrend.rows - }); - - } catch (error) { - console.error('Error fetching analytics:', error); - res.status(500).json({ error: 'Failed to fetch analytics data' }); - } -}; - -export const getAllUsers = async (req: AuthRequest, res: Response) => { - try { - if (req.user.role !== 'admin') { - return res.status(403).json({ error: 'Access denied. Admin role required.' }); - } - - const { page = 1, limit = 20, search = '', role = '', subscription = '' } = req.query; - const offset = (Number(page) - 1) * Number(limit); - - let whereConditions = ['1=1']; - const queryParams: any[] = []; - - if (search) { - whereConditions.push(`(email ILIKE $${queryParams.length + 1} OR first_name ILIKE $${queryParams.length + 1} OR last_name ILIKE $${queryParams.length + 1})`); - queryParams.push(`%${search}%`); - } - - if (role) { - whereConditions.push(`role = $${queryParams.length + 1}`); - queryParams.push(role); - } - - if (subscription) { - whereConditions.push(`subscription_plan = $${queryParams.length + 1}`); - queryParams.push(subscription); - } - - const query = ` - SELECT - id, email, first_name, last_name, role, subscription_plan, subscription_status, - is_verified, last_login_at, created_at, - (SELECT COUNT(*) FROM workflows WHERE user_id = users.id) as workflow_count - FROM users - WHERE ${whereConditions.join(' AND ')} - ORDER BY created_at DESC - LIMIT $${queryParams.length + 1} OFFSET $${queryParams.length + 2} - `; - - queryParams.push(Number(limit), offset); - - const countQuery = ` - SELECT COUNT(*) FROM users WHERE ${whereConditions.join(' AND ')} - `; - - const [users, count] = await Promise.all([ - pool.query(query, queryParams), - pool.query(countQuery, queryParams.slice(0, -2)) - ]); - - res.json({ - users: users.rows, - pagination: { - currentPage: Number(page), - totalPages: Math.ceil(Number(count.rows[0].count) / Number(limit)), - totalUsers: Number(count.rows[0].count), - limit: Number(limit) - } - }); - - } catch (error) { - console.error('Error fetching users:', error); - res.status(500).json({ error: 'Failed to fetch users' }); - } -}; - -export const updateUserRole = async (req: AuthRequest, res: Response) => { - try { - if (req.user.role !== 'admin') { - return res.status(403).json({ error: 'Access denied. Admin role required.' }); - } - - const { userId } = req.params; - const { role, subscription_plan } = req.body; - - const query = ` - UPDATE users - SET role = $1, subscription_plan = $2, updated_at = CURRENT_TIMESTAMP - WHERE id = $3 - RETURNING id, email, role, subscription_plan - `; - - const result = await pool.query(query, [role, subscription_plan, userId]); - - if (result.rows.length === 0) { - return res.status(404).json({ error: 'User not found' }); - } - - // Log the action - await pool.query( - 'INSERT INTO audit_logs (user_id, action, resource_type, resource_id, details) VALUES ($1, $2, $3, $4, $5)', - [req.user.id, 'update_user_role', 'user', userId, { role, subscription_plan }] - ); - - res.json(result.rows[0]); - - } catch (error) { - console.error('Error updating user role:', error); - res.status(500).json({ error: 'Failed to update user role' }); - } -}; - -export const getSystemSettings = async (req: AuthRequest, res: Response) => { - try { - if (req.user.role !== 'admin') { - return res.status(403).json({ error: 'Access denied. Admin role required.' }); - } - - const query = 'SELECT * FROM system_settings ORDER BY key'; - const result = await pool.query(query); - - res.json({ settings: result.rows }); - - } catch (error) { - console.error('Error fetching system settings:', error); - res.status(500).json({ error: 'Failed to fetch system settings' }); - } -}; - -export const updateSystemSetting = async (req: AuthRequest, res: Response) => { - try { - if (req.user.role !== 'admin') { - return res.status(403).json({ error: 'Access denied. Admin role required.' }); - } - - const { key } = req.params; - const { value } = req.body; - - const query = ` - UPDATE system_settings - SET value = $1, updated_by = $2, updated_at = CURRENT_TIMESTAMP - WHERE key = $3 - RETURNING * - `; - - const result = await pool.query(query, [JSON.stringify(value), req.user.id, key]); - - if (result.rows.length === 0) { - return res.status(404).json({ error: 'Setting not found' }); - } - - // Log the action - await pool.query( - 'INSERT INTO audit_logs (user_id, action, resource_type, resource_id, details) VALUES ($1, $2, $3, $4, $5)', - [req.user.id, 'update_system_setting', 'system_setting', key, { value }] - ); - - res.json(result.rows[0]); - - } catch (error) { - console.error('Error updating system setting:', error); - res.status(500).json({ error: 'Failed to update system setting' }); - } -}; \ No newline at end of file diff --git a/backend/src/controllers/authController.ts b/backend/src/controllers/authController.ts deleted file mode 100644 index b413b42..0000000 --- a/backend/src/controllers/authController.ts +++ /dev/null @@ -1,173 +0,0 @@ -import { Request, Response } from 'express'; -import { pool } from '../db/connection'; -import { hashPassword, comparePassword, generateToken, generateRandomToken } from '../utils/auth'; - -export const signup = async (req: Request, res: Response) => { - try { - const { email, password, first_name, last_name } = req.body; - - if (!email || !password) { - return res.status(400).json({ - success: false, - message: 'Email and password are required' - }); - } - - const existingUser = await pool.query('SELECT id FROM users WHERE email = $1', [email]); - if (existingUser.rows.length > 0) { - return res.status(409).json({ - success: false, - message: 'User already exists with this email' - }); - } - - const passwordHash = await hashPassword(password); - const verificationToken = generateRandomToken(); - - const result = await pool.query( - `INSERT INTO users (email, password_hash, first_name, last_name, verification_token, is_verified) - VALUES ($1, $2, $3, $4, $5, $6) - RETURNING id, email, first_name, last_name, role, subscription_plan, subscription_status, created_at`, - [email, passwordHash, first_name, last_name, verificationToken, false] - ); - - const user = result.rows[0]; - const token = generateToken({ - userId: user.id, - email: user.email, - role: user.role, - subscription_plan: user.subscription_plan - }); - - res.status(201).json({ - success: true, - token, - user: { - id: user.id, - email: user.email, - first_name: user.first_name, - last_name: user.last_name, - role: user.role, - subscription_plan: user.subscription_plan, - subscription_status: user.subscription_status, - is_verified: false, - created_at: user.created_at, - updated_at: user.created_at - } - }); - } catch (error) { - console.error('Signup error:', error); - res.status(500).json({ - success: false, - message: 'Internal server error' - }); - } -}; - -export const login = async (req: Request, res: Response) => { - try { - const { email, password } = req.body; - - if (!email || !password) { - return res.status(400).json({ - success: false, - message: 'Email and password are required' - }); - } - - const result = await pool.query( - 'SELECT id, email, password_hash, first_name, last_name, is_verified, role, subscription_plan, subscription_status, created_at, updated_at FROM users WHERE email = $1', - [email] - ); - - if (result.rows.length === 0) { - return res.status(401).json({ - success: false, - message: 'Invalid credentials' - }); - } - - const user = result.rows[0]; - const isValidPassword = await comparePassword(password, user.password_hash); - - if (!isValidPassword) { - return res.status(401).json({ - success: false, - message: 'Invalid credentials' - }); - } - - const token = generateToken({ - userId: user.id, - email: user.email, - role: user.role, - subscription_plan: user.subscription_plan - }); - - res.json({ - success: true, - token, - user: { - id: user.id, - email: user.email, - first_name: user.first_name, - last_name: user.last_name, - is_verified: user.is_verified, - role: user.role, - subscription_plan: user.subscription_plan, - subscription_status: user.subscription_status, - created_at: user.created_at, - updated_at: user.updated_at - } - }); - } catch (error) { - console.error('Login error:', error); - res.status(500).json({ - success: false, - message: 'Internal server error' - }); - } -}; - -export const resetPassword = async (req: Request, res: Response) => { - try { - const { email } = req.body; - - if (!email) { - return res.status(400).json({ - success: false, - message: 'Email is required' - }); - } - - const user = await pool.query('SELECT id FROM users WHERE email = $1', [email]); - if (user.rows.length === 0) { - return res.json({ - success: true, - message: 'If the email exists, a reset link has been sent' - }); - } - - const resetToken = generateRandomToken(); - const resetExpires = new Date(Date.now() + 3600000); // 1 hour - - await pool.query( - 'UPDATE users SET reset_password_token = $1, reset_password_expires = $2 WHERE email = $3', - [resetToken, resetExpires, email] - ); - - // TODO: Send email with reset link - console.log(`Reset token for ${email}: ${resetToken}`); - - res.json({ - success: true, - message: 'If the email exists, a reset link has been sent' - }); - } catch (error) { - console.error('Reset password error:', error); - res.status(500).json({ - success: false, - message: 'Internal server error' - }); - } -}; \ No newline at end of file diff --git a/backend/src/controllers/billingController.ts b/backend/src/controllers/billingController.ts deleted file mode 100644 index c0c8d56..0000000 --- a/backend/src/controllers/billingController.ts +++ /dev/null @@ -1,337 +0,0 @@ -import { Request, Response } from 'express'; -import { pool } from '../db/connection'; -import { AuthRequest } from '../middleware/auth'; - -export const getSubscriptionPlans = async (req: Request, res: Response) => { - try { - const query = ` - SELECT * FROM subscription_plans - WHERE is_active = true - ORDER BY price_monthly ASC - `; - - const result = await pool.query(query); - res.json({ plans: result.rows }); - } catch (error) { - console.error('Error fetching subscription plans:', error); - res.status(500).json({ error: 'Failed to fetch subscription plans' }); - } -}; - -export const getCurrentSubscription = async (req: AuthRequest, res: Response) => { - try { - const userQuery = ` - SELECT - subscription_plan, - subscription_status, - subscription_starts_at, - subscription_ends_at, - workflow_limit, - user_limit, - features - FROM users - WHERE id = $1 - `; - - const userResult = await pool.query(userQuery, [req.user.id]); - - if (userResult.rows.length === 0) { - return res.status(404).json({ error: 'User not found' }); - } - - const subscription = userResult.rows[0]; - - // Get subscription history - const historyQuery = ` - SELECT * FROM subscription_history - WHERE user_id = $1 - ORDER BY created_at DESC - LIMIT 10 - `; - - const historyResult = await pool.query(historyQuery, [req.user.id]); - - // Check if subscription is expired - const now = new Date(); - const expiryDate = new Date(subscription.subscription_ends_at); - const isExpired = subscription.subscription_ends_at && expiryDate < now; - - res.json({ - subscription: { - ...subscription, - is_expired: isExpired, - days_remaining: subscription.subscription_ends_at - ? Math.max(0, Math.ceil((expiryDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24))) - : null - }, - history: historyResult.rows - }); - - } catch (error) { - console.error('Error fetching current subscription:', error); - res.status(500).json({ error: 'Failed to fetch subscription details' }); - } -}; - -export const upgradeSubscription = async (req: AuthRequest, res: Response) => { - try { - const { planName, paymentMethod = 'manual' } = req.body; - - // Get the plan details - const planQuery = ` - SELECT * FROM subscription_plans - WHERE name = $1 AND is_active = true - `; - - const planResult = await pool.query(planQuery, [planName]); - - if (planResult.rows.length === 0) { - return res.status(404).json({ error: 'Subscription plan not found' }); - } - - const plan = planResult.rows[0]; - - // For now, we'll simulate successful payment - // In a real app, this would integrate with Stripe/PayPal/etc. - const now = new Date(); - const endDate = new Date(now); - endDate.setMonth(endDate.getMonth() + 1); // 1 month subscription - - // Start transaction - await pool.query('BEGIN'); - - try { - // Update user subscription - const updateUserQuery = ` - UPDATE users - SET - subscription_plan = $1, - subscription_status = 'active', - subscription_starts_at = $2, - subscription_ends_at = $3, - workflow_limit = $4, - user_limit = $5, - features = $6, - updated_at = CURRENT_TIMESTAMP - WHERE id = $7 - RETURNING * - `; - - const userResult = await pool.query(updateUserQuery, [ - planName, - now, - endDate, - plan.workflow_limit, - plan.user_limit, - plan.features, - req.user.id - ]); - - // Record payment history - const historyQuery = ` - INSERT INTO subscription_history ( - user_id, plan_name, amount, currency, payment_method, - payment_status, billing_period_start, billing_period_end - ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) - RETURNING * - `; - - const historyResult = await pool.query(historyQuery, [ - req.user.id, - planName, - plan.price_monthly, - 'GBP', - paymentMethod, - 'completed', - now, - endDate - ]); - - // Log the action - await pool.query( - 'INSERT INTO audit_logs (user_id, action, resource_type, details) VALUES ($1, $2, $3, $4)', - [req.user.id, 'upgrade_subscription', 'subscription', { from: req.user.subscription_plan, to: planName }] - ); - - await pool.query('COMMIT'); - - res.json({ - message: 'Subscription upgraded successfully', - subscription: userResult.rows[0], - payment: historyResult.rows[0] - }); - - } catch (error) { - await pool.query('ROLLBACK'); - throw error; - } - - } catch (error) { - console.error('Error upgrading subscription:', error); - res.status(500).json({ error: 'Failed to upgrade subscription' }); - } -}; - -export const cancelSubscription = async (req: AuthRequest, res: Response) => { - try { - // Don't actually cancel immediately, just mark for cancellation at period end - const query = ` - UPDATE users - SET - subscription_status = 'cancelled', - updated_at = CURRENT_TIMESTAMP - WHERE id = $1 - RETURNING subscription_plan, subscription_ends_at - `; - - const result = await pool.query(query, [req.user.id]); - - // Log the action - await pool.query( - 'INSERT INTO audit_logs (user_id, action, resource_type, details) VALUES ($1, $2, $3, $4)', - [req.user.id, 'cancel_subscription', 'subscription', { plan: result.rows[0].subscription_plan }] - ); - - res.json({ - message: 'Subscription cancelled. Access will continue until the end of your billing period.', - ends_at: result.rows[0].subscription_ends_at - }); - - } catch (error) { - console.error('Error cancelling subscription:', error); - res.status(500).json({ error: 'Failed to cancel subscription' }); - } -}; - -export const getUsageStats = async (req: AuthRequest, res: Response) => { - try { - // Get current user limits - const userQuery = ` - SELECT workflow_limit, user_limit, features - FROM users - WHERE id = $1 - `; - - const userResult = await pool.query(userQuery, [req.user.id]); - const user = userResult.rows[0]; - - // Get current usage - const workflowCountQuery = ` - SELECT COUNT(*) as count - FROM workflows - WHERE user_id = $1 - `; - - const workflowResult = await pool.query(workflowCountQuery, [req.user.id]); - const currentWorkflows = parseInt(workflowResult.rows[0].count); - - // Get team members count (if applicable) - const teamCountQuery = ` - SELECT COUNT(*) as count - FROM user_teams - WHERE owner_id = $1 AND status = 'active' - `; - - const teamResult = await pool.query(teamCountQuery, [req.user.id]); - const currentTeamMembers = parseInt(teamResult.rows[0].count); - - // Get execution count for current month - const executionCountQuery = ` - SELECT COUNT(*) as count - FROM workflow_executions - WHERE user_id = $1 - AND created_at >= DATE_TRUNC('month', CURRENT_DATE) - `; - - const executionResult = await pool.query(executionCountQuery, [req.user.id]); - const currentExecutions = parseInt(executionResult.rows[0].count); - - // Get execution limit from features - const executionLimit = user.features?.execution_limit || 100; - - res.json({ - limits: { - workflows: user.workflow_limit, - teamMembers: user.user_limit, - executions: executionLimit - }, - usage: { - workflows: currentWorkflows, - teamMembers: currentTeamMembers, - executions: currentExecutions - }, - percentages: { - workflows: user.workflow_limit === -1 ? 0 : Math.round((currentWorkflows / user.workflow_limit) * 100), - teamMembers: user.user_limit === -1 ? 0 : Math.round((currentTeamMembers / user.user_limit) * 100), - executions: executionLimit === -1 ? 0 : Math.round((currentExecutions / executionLimit) * 100) - } - }); - - } catch (error) { - console.error('Error fetching usage stats:', error); - res.status(500).json({ error: 'Failed to fetch usage statistics' }); - } -}; - -// Webhook endpoint for payment provider notifications (Stripe, PayPal, etc.) -export const handlePaymentWebhook = async (req: Request, res: Response) => { - try { - // This would contain the logic to handle payment provider webhooks - // For now, just return success - console.log('Payment webhook received:', req.body); - res.status(200).json({ received: true }); - } catch (error) { - console.error('Error handling payment webhook:', error); - res.status(500).json({ error: 'Webhook processing failed' }); - } -}; - -export const generateInvoice = async (req: AuthRequest, res: Response) => { - try { - const { paymentId } = req.params; - - const query = ` - SELECT - sh.*, - u.email, - u.first_name, - u.last_name - FROM subscription_history sh - JOIN users u ON sh.user_id = u.id - WHERE sh.id = $1 AND sh.user_id = $2 - `; - - const result = await pool.query(query, [paymentId, req.user.id]); - - if (result.rows.length === 0) { - return res.status(404).json({ error: 'Invoice not found' }); - } - - const invoice = result.rows[0]; - - // In a real app, you'd generate a PDF here - // For now, return invoice data - res.json({ - invoice: { - id: invoice.id, - date: invoice.created_at, - customer: { - name: `${invoice.first_name} ${invoice.last_name}`, - email: invoice.email - }, - plan: invoice.plan_name, - amount: invoice.amount, - currency: invoice.currency, - period: { - start: invoice.billing_period_start, - end: invoice.billing_period_end - }, - status: invoice.payment_status - } - }); - - } catch (error) { - console.error('Error generating invoice:', error); - res.status(500).json({ error: 'Failed to generate invoice' }); - } -}; \ No newline at end of file diff --git a/backend/src/controllers/chatController.ts b/backend/src/controllers/chatController.ts deleted file mode 100644 index 9a6f94b..0000000 --- a/backend/src/controllers/chatController.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { Response } from 'express'; -import { query } from '../utils/db'; -import { AuthRequest } from '../middleware/auth'; -import { generateRandomToken } from '../utils/auth'; - -const mockResponses: { [key: string]: string } = { - 'how to connect instagram': 'To connect Instagram, go to Integrations > Instagram > Connect. You\'ll need to authorize our app to access your Instagram account.', - 'how to create webhook': 'To create a webhook, go to Webhooks > Create New. Choose your trigger type and we\'ll generate a unique URL for you.', - 'workflow not working': 'Check the Logs section to see execution details. Common issues include expired tokens or invalid trigger conditions.', - 'default': 'I\'m here to help! You can ask me about connecting integrations, creating workflows, troubleshooting issues, or navigating the platform.' -}; - -export const sendMessage = async (req: AuthRequest, res: Response) => { - try { - const { message, session_id } = req.body; - - if (!message) { - return res.status(400).json({ - success: false, - message: 'Message is required' - }); - } - - const sessionId = session_id || generateRandomToken(); - - await query( - 'INSERT INTO chat_history (user_id, session_id, message_type, content) VALUES ($1, $2, $3, $4)', - [req.user?.id, sessionId, 'user', message] - ); - - const lowerMessage = message.toLowerCase(); - let reply = mockResponses.default; - - for (const [key, value] of Object.entries(mockResponses)) { - if (lowerMessage.includes(key)) { - reply = value; - break; - } - } - - await query( - 'INSERT INTO chat_history (user_id, session_id, message_type, content) VALUES ($1, $2, $3, $4)', - [req.user?.id, sessionId, 'assistant', reply] - ); - - res.json({ - success: true, - reply, - session_id: sessionId - }); - } catch (error) { - console.error('Send message error:', error); - res.status(500).json({ - success: false, - message: 'Internal server error' - }); - } -}; - -export const getChatHistory = async (req: AuthRequest, res: Response) => { - try { - const { session_id } = req.query; - - let queryText = ` - SELECT message_type, content, created_at - FROM chat_history - WHERE user_id = $1 - `; - const params: any[] = [req.user?.id]; - - if (session_id) { - queryText += ' AND session_id = $2'; - params.push(session_id); - } - - queryText += ' ORDER BY created_at ASC'; - - const result = await query(queryText, params); - - res.json({ - success: true, - messages: result.rows - }); - } catch (error) { - console.error('Get chat history error:', error); - res.status(500).json({ - success: false, - message: 'Internal server error' - }); - } -}; \ No newline at end of file diff --git a/backend/src/controllers/integrationController.ts b/backend/src/controllers/integrationController.ts deleted file mode 100644 index 3779538..0000000 --- a/backend/src/controllers/integrationController.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { Response } from 'express'; -import { query } from '../utils/db'; -import { AuthRequest } from '../middleware/auth'; - -export const getIntegrations = async (req: AuthRequest, res: Response) => { - try { - const result = await query( - `SELECT id, provider, account_name, account_email, is_active, created_at, updated_at - FROM integrations WHERE user_id = $1 ORDER BY provider`, - [req.user?.id] - ); - - res.json({ - success: true, - integrations: result.rows - }); - } catch (error) { - console.error('Get integrations error:', error); - res.status(500).json({ - success: false, - message: 'Internal server error' - }); - } -}; - -export const connectIntegration = async (req: AuthRequest, res: Response) => { - try { - const { provider } = req.params; - const { access_token, refresh_token, account_name, account_email, scopes } = req.body; - - if (!access_token) { - return res.status(400).json({ - success: false, - message: 'Access token is required' - }); - } - - const existing = await query( - 'SELECT id FROM integrations WHERE user_id = $1 AND provider = $2', - [req.user?.id, provider] - ); - - if (existing.rows.length > 0) { - const result = await query( - `UPDATE integrations SET access_token = $1, refresh_token = $2, account_name = $3, - account_email = $4, scopes = $5, is_active = true, updated_at = CURRENT_TIMESTAMP - WHERE user_id = $6 AND provider = $7 - RETURNING id, provider, account_name, account_email, is_active`, - [access_token, refresh_token, account_name, account_email, scopes, req.user?.id, provider] - ); - - return res.json({ - success: true, - message: 'Integration updated successfully', - integration: result.rows[0] - }); - } - - const result = await query( - `INSERT INTO integrations (user_id, provider, access_token, refresh_token, account_name, account_email, scopes) - VALUES ($1, $2, $3, $4, $5, $6, $7) - RETURNING id, provider, account_name, account_email, is_active, created_at`, - [req.user?.id, provider, access_token, refresh_token, account_name, account_email, scopes] - ); - - res.status(201).json({ - success: true, - message: 'Integration connected successfully', - integration: result.rows[0] - }); - } catch (error) { - console.error('Connect integration error:', error); - res.status(500).json({ - success: false, - message: 'Internal server error' - }); - } -}; - -export const disconnectIntegration = async (req: AuthRequest, res: Response) => { - try { - const { id } = req.params; - - const result = await query( - 'DELETE FROM integrations WHERE id = $1 AND user_id = $2 RETURNING id', - [id, req.user?.id] - ); - - if (result.rows.length === 0) { - return res.status(404).json({ - success: false, - message: 'Integration not found' - }); - } - - res.json({ - success: true, - message: 'Integration disconnected successfully' - }); - } catch (error) { - console.error('Disconnect integration error:', error); - res.status(500).json({ - success: false, - message: 'Internal server error' - }); - } -}; \ No newline at end of file diff --git a/backend/src/controllers/logController.ts b/backend/src/controllers/logController.ts deleted file mode 100644 index 20ab75f..0000000 --- a/backend/src/controllers/logController.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { Response } from 'express'; -import { query } from '../utils/db'; -import { AuthRequest } from '../middleware/auth'; - -export const getWorkflowExecutions = async (req: AuthRequest, res: Response) => { - try { - const { workflow_id, status, limit = 100 } = req.query; - - let queryText = ` - SELECT we.id, we.workflow_id, w.name as workflow_name, we.status, we.trigger_data, - we.error_message, we.started_at, we.finished_at, we.created_at - FROM workflow_executions we - JOIN workflows w ON we.workflow_id = w.id - WHERE we.user_id = $1 - `; - const params: any[] = [req.user?.id]; - let paramCount = 1; - - if (workflow_id) { - paramCount++; - queryText += ` AND we.workflow_id = $${paramCount}`; - params.push(workflow_id); - } - - if (status) { - paramCount++; - queryText += ` AND we.status = $${paramCount}`; - params.push(status); - } - - queryText += ` ORDER BY we.created_at DESC LIMIT $${paramCount + 1}`; - params.push(limit); - - const result = await query(queryText, params); - - res.json({ - success: true, - executions: result.rows - }); - } catch (error) { - console.error('Get workflow executions error:', error); - res.status(500).json({ - success: false, - message: 'Internal server error' - }); - } -}; - -export const getExecutionDetails = async (req: AuthRequest, res: Response) => { - try { - const { id } = req.params; - - const result = await query( - `SELECT we.*, w.name as workflow_name - FROM workflow_executions we - JOIN workflows w ON we.workflow_id = w.id - WHERE we.id = $1 AND we.user_id = $2`, - [id, req.user?.id] - ); - - if (result.rows.length === 0) { - return res.status(404).json({ - success: false, - message: 'Execution not found' - }); - } - - res.json({ - success: true, - execution: result.rows[0] - }); - } catch (error) { - console.error('Get execution details error:', error); - res.status(500).json({ - success: false, - message: 'Internal server error' - }); - } -}; \ No newline at end of file diff --git a/backend/src/controllers/templateController.ts b/backend/src/controllers/templateController.ts deleted file mode 100644 index 25425fa..0000000 --- a/backend/src/controllers/templateController.ts +++ /dev/null @@ -1,198 +0,0 @@ -import { Request, Response } from 'express'; -import { pool } from '../db/connection'; -import { AuthRequest } from '../middleware/auth'; -import { n8nService } from '../services/n8nService'; - -export const getTemplates = async (req: AuthRequest, res: Response) => { - try { - const { category, search } = req.query; - const userRole = req.user?.role || 'free'; - - // Build query for local templates - let queryText = ` - SELECT id, name, description, category, trigger_type, tags, is_featured, install_count, created_at - FROM templates WHERE 1=1 - `; - const params: any[] = []; - let paramCount = 0; - - if (category) { - paramCount++; - queryText += ` AND category = $${paramCount}`; - params.push(category); - } - - if (search) { - paramCount++; - queryText += ` AND (name ILIKE $${paramCount} OR description ILIKE $${paramCount})`; - params.push(`%${search}%`); - } - - queryText += ' ORDER BY is_featured DESC, install_count DESC, created_at DESC'; - - // Get local templates - const localResult = await pool.query(queryText, params); - let templates = localResult.rows.map(template => ({ - ...template, - source: 'local' - })); - - // For admin users, also fetch templates from n8n - if (userRole === 'admin') { - try { - const n8nWorkflows = await n8nService.getWorkflows(); - - const n8nTemplates = n8nWorkflows.map(workflow => ({ - id: `n8n_${workflow.id}`, - name: workflow.name, - description: `N8n workflow: ${workflow.name}`, - category: 'n8n', - trigger_type: 'n8n_workflow', - tags: ['n8n', 'automation'], - is_featured: false, - install_count: 0, - created_at: workflow.createdAt, - source: 'n8n', - n8n_workflow_id: workflow.id, - n8n_data: workflow - })); - - // Filter n8n templates if search is provided - if (search) { - const searchTerm = search.toString().toLowerCase(); - const filteredN8nTemplates = n8nTemplates.filter(template => - template.name.toLowerCase().includes(searchTerm) || - template.description.toLowerCase().includes(searchTerm) - ); - templates = [...templates, ...filteredN8nTemplates]; - } else { - templates = [...templates, ...n8nTemplates]; - } - } catch (n8nError) { - console.error('Error fetching n8n workflows:', n8nError); - // Continue with local templates only - } - } - - res.json({ - success: true, - templates: templates - }); - } catch (error) { - console.error('Get templates error:', error); - res.status(500).json({ - success: false, - message: 'Internal server error' - }); - } -}; - -export const installTemplate = async (req: AuthRequest, res: Response) => { - try { - const { id } = req.params; - const { workflow_name } = req.body; - - // Check if it's an n8n template - if (id.startsWith('n8n_')) { - const n8nWorkflowId = id.replace('n8n_', ''); - - try { - // Get the n8n workflow - const n8nWorkflow = await n8nService.getWorkflow(n8nWorkflowId); - - // Create workflow in our database that references the n8n workflow - const workflowResult = await pool.query( - `INSERT INTO workflows (user_id, name, description, trigger_type, n8n_workflow_id, status, is_active) - VALUES ($1, $2, $3, $4, $5, $6, $7) - RETURNING id`, - [ - req.user?.id, - workflow_name || n8nWorkflow.name, - `N8n workflow: ${n8nWorkflow.name}`, - 'n8n_workflow', - n8nWorkflowId, - 'connected', - n8nWorkflow.active - ] - ); - - const workflowId = workflowResult.rows[0].id; - - res.status(201).json({ - success: true, - message: 'N8n workflow connected successfully', - workflow_id: workflowId, - n8n_workflow_id: n8nWorkflowId - }); - - } catch (n8nError) { - console.error('Error connecting n8n workflow:', n8nError); - return res.status(500).json({ - success: false, - message: 'Failed to connect n8n workflow' - }); - } - } else { - // Handle local template installation - const template = await pool.query('SELECT * FROM templates WHERE id = $1', [id]); - if (template.rows.length === 0) { - return res.status(404).json({ - success: false, - message: 'Template not found' - }); - } - - const templateData = template.rows[0]; - const workflowName = workflow_name || templateData.name; - - // Check user's workflow limit - const userQuery = await pool.query('SELECT workflow_limit FROM users WHERE id = $1', [req.user?.id]); - const userWorkflowLimit = userQuery.rows[0]?.workflow_limit || 3; - - const currentWorkflowsQuery = await pool.query( - 'SELECT COUNT(*) as count FROM workflows WHERE user_id = $1', - [req.user?.id] - ); - const currentWorkflowCount = parseInt(currentWorkflowsQuery.rows[0].count); - - if (userWorkflowLimit !== -1 && currentWorkflowCount >= userWorkflowLimit) { - return res.status(403).json({ - success: false, - message: 'Workflow limit reached. Please upgrade your plan to create more workflows.' - }); - } - - const workflowResult = await pool.query( - `INSERT INTO workflows (user_id, name, description, trigger_type, trigger_config, actions_config) - VALUES ($1, $2, $3, $4, $5, $6) - RETURNING id`, - [req.user?.id, workflowName, templateData.description, templateData.trigger_type, - templateData.trigger_config, templateData.actions_config] - ); - - const workflowId = workflowResult.rows[0].id; - - await pool.query( - 'INSERT INTO user_templates (user_id, template_id, workflow_id) VALUES ($1, $2, $3)', - [req.user?.id, id, workflowId] - ); - - await pool.query( - 'UPDATE templates SET install_count = install_count + 1 WHERE id = $1', - [id] - ); - - res.status(201).json({ - success: true, - message: 'Template installed successfully', - workflow_id: workflowId - }); - } - } catch (error) { - console.error('Install template error:', error); - res.status(500).json({ - success: false, - message: 'Internal server error' - }); - } -}; \ No newline at end of file diff --git a/backend/src/controllers/webhookController.ts b/backend/src/controllers/webhookController.ts deleted file mode 100644 index 3520675..0000000 --- a/backend/src/controllers/webhookController.ts +++ /dev/null @@ -1,167 +0,0 @@ -import { Request, Response } from 'express'; -import { query } from '../utils/db'; -import { AuthRequest } from '../middleware/auth'; -import { generateRandomToken } from '../utils/auth'; - -export const getWebhooks = async (req: AuthRequest, res: Response) => { - try { - const result = await query( - `SELECT id, name, slug, trigger_type, url_path, is_active, created_at, updated_at - FROM webhooks WHERE user_id = $1 ORDER BY created_at DESC`, - [req.user?.id] - ); - - res.json({ - success: true, - webhooks: result.rows - }); - } catch (error) { - console.error('Get webhooks error:', error); - res.status(500).json({ - success: false, - message: 'Internal server error' - }); - } -}; - -export const createWebhook = async (req: AuthRequest, res: Response) => { - try { - const { name, trigger_type } = req.body; - - if (!name || !trigger_type) { - return res.status(400).json({ - success: false, - message: 'Name and trigger_type are required' - }); - } - - const slug = name.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, ''); - const secretKey = generateRandomToken(); - const urlPath = `/webhook/${req.user?.id}/${slug}`; - - const result = await query( - `INSERT INTO webhooks (user_id, name, slug, trigger_type, secret_key, url_path) - VALUES ($1, $2, $3, $4, $5, $6) - RETURNING id, name, slug, trigger_type, url_path, is_active, created_at`, - [req.user?.id, name, slug, trigger_type, secretKey, urlPath] - ); - - res.status(201).json({ - success: true, - webhook: { - ...result.rows[0], - secret_key: secretKey - } - }); - } catch (error) { - console.error('Create webhook error:', error); - res.status(500).json({ - success: false, - message: 'Internal server error' - }); - } -}; - -export const getWebhookLogs = async (req: AuthRequest, res: Response) => { - try { - const { id } = req.params; - const { limit = 50 } = req.query; - - const webhook = await query( - 'SELECT id FROM webhooks WHERE id = $1 AND user_id = $2', - [id, req.user?.id] - ); - - if (webhook.rows.length === 0) { - return res.status(404).json({ - success: false, - message: 'Webhook not found' - }); - } - - const result = await query( - `SELECT id, request_method, request_headers, response_status, processing_time_ms, created_at - FROM webhook_logs WHERE webhook_id = $1 ORDER BY created_at DESC LIMIT $2`, - [id, limit] - ); - - res.json({ - success: true, - logs: result.rows - }); - } catch (error) { - console.error('Get webhook logs error:', error); - res.status(500).json({ - success: false, - message: 'Internal server error' - }); - } -}; - -export const deleteWebhook = async (req: AuthRequest, res: Response) => { - try { - const { id } = req.params; - - const result = await query( - 'DELETE FROM webhooks WHERE id = $1 AND user_id = $2 RETURNING id', - [id, req.user?.id] - ); - - if (result.rows.length === 0) { - return res.status(404).json({ - success: false, - message: 'Webhook not found' - }); - } - - res.json({ - success: true, - message: 'Webhook deleted successfully' - }); - } catch (error) { - console.error('Delete webhook error:', error); - res.status(500).json({ - success: false, - message: 'Internal server error' - }); - } -}; - -export const handleWebhookCall = async (req: Request, res: Response) => { - try { - const { user_id, slug } = req.params; - const startTime = Date.now(); - - const webhook = await query( - 'SELECT id, secret_key FROM webhooks WHERE url_path = $1 AND is_active = true', - [`/webhook/${user_id}/${slug}`] - ); - - if (webhook.rows.length === 0) { - return res.status(404).json({ - success: false, - message: 'Webhook not found' - }); - } - - const processingTime = Date.now() - startTime; - - await query( - `INSERT INTO webhook_logs (webhook_id, request_method, request_headers, request_payload, response_status, processing_time_ms) - VALUES ($1, $2, $3, $4, $5, $6)`, - [webhook.rows[0].id, req.method, req.headers, req.body, 200, processingTime] - ); - - res.json({ - success: true, - message: 'Webhook received successfully', - timestamp: new Date().toISOString() - }); - } catch (error) { - console.error('Handle webhook error:', error); - res.status(500).json({ - success: false, - message: 'Internal server error' - }); - } -}; \ No newline at end of file diff --git a/backend/src/controllers/workflowController.ts b/backend/src/controllers/workflowController.ts deleted file mode 100644 index 6e80f56..0000000 --- a/backend/src/controllers/workflowController.ts +++ /dev/null @@ -1,456 +0,0 @@ -import { Response } from 'express'; -import { query } from '../utils/db'; -import { AuthRequest } from '../middleware/auth'; -import n8nService from '../services/n8nService'; - -export const getWorkflows = async (req: AuthRequest, res: Response) => { - try { - // Get workflows from n8n - const n8nWorkflows = await n8nService.getWorkflows(); - - // Get local workflow metadata - const localResult = await query( - `SELECT id, name, n8n_workflow_id, description, status, trigger_type, is_active, created_at, updated_at - FROM workflows WHERE user_id = $1 ORDER BY created_at DESC`, - [req.user?.id] - ); - - // Merge n8n data with local metadata - const workflows = localResult.rows.map(localWorkflow => { - const n8nWorkflow = n8nWorkflows.find(w => w.id === localWorkflow.n8n_workflow_id); - return { - ...localWorkflow, - n8n_data: n8nWorkflow, - active: n8nWorkflow?.active || false, - status: n8nWorkflow?.active ? 'active' : 'inactive' - }; - }); - - res.json({ - success: true, - workflows, - total_n8n_workflows: n8nWorkflows.length - }); - } catch (error) { - console.error('Get workflows error:', error); - res.status(500).json({ - success: false, - message: 'Failed to fetch workflows' - }); - } -}; - -export const getWorkflow = async (req: AuthRequest, res: Response) => { - try { - const { id } = req.params; - - // Get local workflow - const localResult = await query( - `SELECT * FROM workflows WHERE id = $1 AND user_id = $2`, - [id, req.user?.id] - ); - - if (localResult.rows.length === 0) { - return res.status(404).json({ - success: false, - message: 'Workflow not found' - }); - } - - const localWorkflow = localResult.rows[0]; - - // Get n8n workflow if exists - let n8nWorkflow = null; - if (localWorkflow.n8n_workflow_id) { - try { - n8nWorkflow = await n8nService.getWorkflow(localWorkflow.n8n_workflow_id); - } catch (error) { - console.error('Failed to fetch n8n workflow:', error); - } - } - - res.json({ - success: true, - workflow: { - ...localWorkflow, - n8n_data: n8nWorkflow - } - }); - } catch (error) { - console.error('Get workflow error:', error); - res.status(500).json({ - success: false, - message: 'Internal server error' - }); - } -}; - -export const createWorkflow = async (req: AuthRequest, res: Response) => { - try { - const { name, description, trigger_type, trigger_config, actions_config, n8n_workflow_data } = req.body; - - if (!name) { - return res.status(400).json({ - success: false, - message: 'Name is required' - }); - } - - let n8nWorkflowId = null; - - // Create workflow in n8n if workflow data provided - if (n8n_workflow_data) { - try { - const n8nWorkflow = await n8nService.createWorkflow({ - name, - active: false, - nodes: n8n_workflow_data.nodes || [], - connections: n8n_workflow_data.connections || {}, - settings: n8n_workflow_data.settings, - staticData: n8n_workflow_data.staticData - }); - n8nWorkflowId = n8nWorkflow.id; - } catch (error) { - console.error('Failed to create n8n workflow:', error); - return res.status(500).json({ - success: false, - message: 'Failed to create workflow in n8n' - }); - } - } - - // Save to local database - const result = await query( - `INSERT INTO workflows (user_id, name, description, trigger_type, trigger_config, actions_config, n8n_workflow_id) - VALUES ($1, $2, $3, $4, $5, $6, $7) - RETURNING id, name, description, status, trigger_type, is_active, created_at`, - [req.user?.id, name, description, trigger_type, trigger_config, actions_config, n8nWorkflowId] - ); - - res.status(201).json({ - success: true, - workflow: { - ...result.rows[0], - n8n_workflow_id: n8nWorkflowId - } - }); - } catch (error) { - console.error('Create workflow error:', error); - res.status(500).json({ - success: false, - message: 'Internal server error' - }); - } -}; - -export const updateWorkflow = async (req: AuthRequest, res: Response) => { - try { - const { id } = req.params; - const { name, description, trigger_type, trigger_config, actions_config, n8n_workflow_data } = req.body; - - // Get existing workflow - const existingResult = await query( - `SELECT * FROM workflows WHERE id = $1 AND user_id = $2`, - [id, req.user?.id] - ); - - if (existingResult.rows.length === 0) { - return res.status(404).json({ - success: false, - message: 'Workflow not found' - }); - } - - const existingWorkflow = existingResult.rows[0]; - - // Update n8n workflow if exists - if (existingWorkflow.n8n_workflow_id && n8n_workflow_data) { - try { - await n8nService.updateWorkflow(existingWorkflow.n8n_workflow_id, { - name, - nodes: n8n_workflow_data.nodes, - connections: n8n_workflow_data.connections, - settings: n8n_workflow_data.settings, - staticData: n8n_workflow_data.staticData - }); - } catch (error) { - console.error('Failed to update n8n workflow:', error); - return res.status(500).json({ - success: false, - message: 'Failed to update workflow in n8n' - }); - } - } - - // Update local database - const result = await query( - `UPDATE workflows - SET name = $1, description = $2, trigger_type = $3, trigger_config = $4, actions_config = $5, updated_at = CURRENT_TIMESTAMP - WHERE id = $6 AND user_id = $7 - RETURNING id, name, description, status, trigger_type, is_active, created_at, updated_at`, - [name, description, trigger_type, trigger_config, actions_config, id, req.user?.id] - ); - - res.json({ - success: true, - workflow: result.rows[0] - }); - } catch (error) { - console.error('Update workflow error:', error); - res.status(500).json({ - success: false, - message: 'Internal server error' - }); - } -}; - -export const activateWorkflow = async (req: AuthRequest, res: Response) => { - try { - const { id } = req.params; - - // Get workflow - const workflowResult = await query( - `SELECT * FROM workflows WHERE id = $1 AND user_id = $2`, - [id, req.user?.id] - ); - - if (workflowResult.rows.length === 0) { - return res.status(404).json({ - success: false, - message: 'Workflow not found' - }); - } - - const workflow = workflowResult.rows[0]; - - // Activate in n8n - if (workflow.n8n_workflow_id) { - try { - await n8nService.activateWorkflow(workflow.n8n_workflow_id); - } catch (error) { - console.error('Failed to activate n8n workflow:', error); - return res.status(500).json({ - success: false, - message: 'Failed to activate workflow in n8n' - }); - } - } - - // Update local status - await query( - `UPDATE workflows SET is_active = true, status = 'active', updated_at = CURRENT_TIMESTAMP WHERE id = $1 AND user_id = $2`, - [id, req.user?.id] - ); - - res.json({ - success: true, - message: 'Workflow activated successfully' - }); - } catch (error) { - console.error('Activate workflow error:', error); - res.status(500).json({ - success: false, - message: 'Internal server error' - }); - } -}; - -export const deactivateWorkflow = async (req: AuthRequest, res: Response) => { - try { - const { id } = req.params; - - // Get workflow - const workflowResult = await query( - `SELECT * FROM workflows WHERE id = $1 AND user_id = $2`, - [id, req.user?.id] - ); - - if (workflowResult.rows.length === 0) { - return res.status(404).json({ - success: false, - message: 'Workflow not found' - }); - } - - const workflow = workflowResult.rows[0]; - - // Deactivate in n8n - if (workflow.n8n_workflow_id) { - try { - await n8nService.deactivateWorkflow(workflow.n8n_workflow_id); - } catch (error) { - console.error('Failed to deactivate n8n workflow:', error); - return res.status(500).json({ - success: false, - message: 'Failed to deactivate workflow in n8n' - }); - } - } - - // Update local status - await query( - `UPDATE workflows SET is_active = false, status = 'inactive', updated_at = CURRENT_TIMESTAMP WHERE id = $1 AND user_id = $2`, - [id, req.user?.id] - ); - - res.json({ - success: true, - message: 'Workflow deactivated successfully' - }); - } catch (error) { - console.error('Deactivate workflow error:', error); - res.status(500).json({ - success: false, - message: 'Internal server error' - }); - } -}; - -export const executeWorkflow = async (req: AuthRequest, res: Response) => { - try { - const { id } = req.params; - const { inputData } = req.body; - - // Get workflow - const workflowResult = await query( - `SELECT * FROM workflows WHERE id = $1 AND user_id = $2`, - [id, req.user?.id] - ); - - if (workflowResult.rows.length === 0) { - return res.status(404).json({ - success: false, - message: 'Workflow not found' - }); - } - - const workflow = workflowResult.rows[0]; - - if (!workflow.n8n_workflow_id) { - return res.status(400).json({ - success: false, - message: 'Workflow is not connected to n8n' - }); - } - - // Execute in n8n - try { - const execution = await n8nService.executeWorkflow(workflow.n8n_workflow_id, inputData); - - // Log execution in database - await query( - `INSERT INTO workflow_executions (workflow_id, user_id, n8n_execution_id, status, trigger_data, started_at) - VALUES ($1, $2, $3, $4, $5, $6)`, - [id, req.user?.id, execution.id, execution.finished ? 'completed' : 'running', inputData, new Date()] - ); - - res.json({ - success: true, - execution - }); - } catch (error) { - console.error('Failed to execute workflow:', error); - res.status(500).json({ - success: false, - message: 'Failed to execute workflow' - }); - } - } catch (error) { - console.error('Execute workflow error:', error); - res.status(500).json({ - success: false, - message: 'Internal server error' - }); - } -}; - -export const deleteWorkflow = async (req: AuthRequest, res: Response) => { - try { - const { id } = req.params; - - // Get workflow - const workflowResult = await query( - `SELECT * FROM workflows WHERE id = $1 AND user_id = $2`, - [id, req.user?.id] - ); - - if (workflowResult.rows.length === 0) { - return res.status(404).json({ - success: false, - message: 'Workflow not found' - }); - } - - const workflow = workflowResult.rows[0]; - - // Delete from n8n first - if (workflow.n8n_workflow_id) { - try { - await n8nService.deleteWorkflow(workflow.n8n_workflow_id); - } catch (error) { - console.error('Failed to delete n8n workflow:', error); - // Continue with local deletion even if n8n deletion fails - } - } - - // Delete from local database - await query( - 'DELETE FROM workflows WHERE id = $1 AND user_id = $2', - [id, req.user?.id] - ); - - res.json({ - success: true, - message: 'Workflow deleted successfully' - }); - } catch (error) { - console.error('Delete workflow error:', error); - res.status(500).json({ - success: false, - message: 'Internal server error' - }); - } -}; - -export const getWorkflowExecutions = async (req: AuthRequest, res: Response) => { - try { - const { id } = req.params; - const limit = parseInt(req.query.limit as string) || 20; - - // Get workflow - const workflowResult = await query( - `SELECT * FROM workflows WHERE id = $1 AND user_id = $2`, - [id, req.user?.id] - ); - - if (workflowResult.rows.length === 0) { - return res.status(404).json({ - success: false, - message: 'Workflow not found' - }); - } - - const workflow = workflowResult.rows[0]; - - if (!workflow.n8n_workflow_id) { - return res.status(400).json({ - success: false, - message: 'Workflow is not connected to n8n' - }); - } - - // Get executions from n8n - const executions = await n8nService.getExecutions(workflow.n8n_workflow_id, limit); - - res.json({ - success: true, - executions - }); - } catch (error) { - console.error('Get workflow executions error:', error); - res.status(500).json({ - success: false, - message: 'Internal server error' - }); - } -}; \ No newline at end of file diff --git a/backend/src/db/connection.ts b/backend/src/db/connection.ts deleted file mode 100644 index 58deb16..0000000 --- a/backend/src/db/connection.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Pool } from 'pg'; - -const pool = new Pool({ - host: process.env.DB_HOST || 'localhost', - port: parseInt(process.env.DB_PORT || '5432'), - database: process.env.DB_NAME || 'saas_automation', - user: process.env.DB_USER || 'postgres', - password: process.env.DB_PASSWORD || 'password', -}); - -// Test connection -pool.on('connect', () => { - console.log('Connected to PostgreSQL database'); -}); - -pool.on('error', (err) => { - console.error('PostgreSQL connection error:', err); -}); - -export { pool }; \ No newline at end of file diff --git a/backend/src/index.ts b/backend/src/index.ts deleted file mode 100644 index cdf8d64..0000000 --- a/backend/src/index.ts +++ /dev/null @@ -1,713 +0,0 @@ -import express from 'express'; -import cors from 'cors'; -import helmet from 'helmet'; -import dotenv from 'dotenv'; - -dotenv.config(); - -const app = express(); -const PORT = process.env.PORT || 3001; - -app.use(helmet()); -app.use(cors()); -app.use(express.json()); - -app.get('/health', (req, res) => { - res.json({ status: 'OK', timestamp: new Date().toISOString() }); -}); - -// Simple test route -app.get('/test', (req, res) => { - res.json({ message: 'Backend is working!' }); -}); - -// Simple auth endpoints for testing -app.post('/auth/login', async (req, res) => { - try { - const { email, password } = req.body; - - if (!email || !password) { - return res.status(400).json({ - success: false, - message: 'Email and password are required' - }); - } - - // For now, just check against our known admin user - if (email === 'info@ai-impress.com' && password === 'admin123') { - const token = 'test-admin-token-123'; - const user = { - id: 1, - email: 'info@ai-impress.com', - first_name: 'Global', - last_name: 'Admin', - role: 'admin', - subscription_plan: 'enterprise', - subscription_status: 'active', - is_verified: true, - created_at: new Date().toISOString(), - updated_at: new Date().toISOString() - }; - - return res.json({ - success: true, - token, - user - }); - } - - return res.status(401).json({ - success: false, - message: 'Invalid credentials' - }); - - } catch (error) { - console.error('Login error:', error); - res.status(500).json({ - success: false, - message: 'Internal server error' - }); - } -}); - -app.post('/auth/signup', async (req, res) => { - try { - const { email, password, first_name, last_name } = req.body; - - if (!email || !password) { - return res.status(400).json({ - success: false, - message: 'Email and password are required' - }); - } - - // Simple mock signup - const token = 'test-user-token-456'; - const user = { - id: 2, - email, - first_name: first_name || '', - last_name: last_name || '', - role: 'free', - subscription_plan: 'free', - subscription_status: 'active', - is_verified: false, - created_at: new Date().toISOString(), - updated_at: new Date().toISOString() - }; - - res.status(201).json({ - success: true, - token, - user - }); - - } catch (error) { - console.error('Signup error:', error); - res.status(500).json({ - success: false, - message: 'Internal server error' - }); - } -}); - -// Admin Analytics endpoint -app.get('/admin/analytics', (req, res) => { - try { - // Mock analytics data - const analytics = { - userStats: { - total_users: 156, - free_users: 120, - pro_users: 28, - enterprise_users: 6, - admin_users: 2, - verified_users: 134, - active_last_7_days: 89, - new_last_30_days: 23 - }, - workflowStats: { - total_workflows: 342, - active_workflows: 278, - new_workflows_30_days: 45, - activation_rate: 81.2 - }, - executionStats: { - total_executions: 12847, - successful_executions: 12234, - executions_24h: 234, - executions_7d: 1876 - }, - revenueStats: { - total_revenue: 18750.00, - revenue_30_days: 4200.00, - successful_payments: 34, - average_order_value: 150.00 - }, - integrationStats: [ - { provider: 'telegram', count: 45 }, - { provider: 'slack', count: 38 }, - { provider: 'gmail', count: 67 }, - { provider: 'teams', count: 23 } - ], - recentActivity: [ - { - action: 'create_workflow', - resource_type: 'workflow', - created_at: new Date(Date.now() - 1000 * 60 * 5).toISOString(), - user_email: 'john@example.com' - }, - { - action: 'upgrade_subscription', - resource_type: 'subscription', - created_at: new Date(Date.now() - 1000 * 60 * 15).toISOString(), - user_email: 'sarah@company.com' - }, - { - action: 'execute_workflow', - resource_type: 'workflow', - created_at: new Date(Date.now() - 1000 * 60 * 8).toISOString(), - user_email: 'mike@startup.io' - }, - { - action: 'create_integration', - resource_type: 'integration', - created_at: new Date(Date.now() - 1000 * 60 * 22).toISOString(), - user_email: 'lisa@agency.com' - }, - { - action: 'login', - resource_type: 'auth', - created_at: new Date(Date.now() - 1000 * 60 * 3).toISOString(), - user_email: 'admin@platform.com' - } - ], - topUsers: [ - { - email: 'power.user@company.com', - first_name: 'Alex', - last_name: 'Johnson', - subscription_plan: 'enterprise', - workflow_count: 24, - last_login_at: new Date(Date.now() - 1000 * 60 * 30).toISOString() - }, - { - email: 'busy.bee@startup.io', - first_name: 'Maria', - last_name: 'Garcia', - subscription_plan: 'pro', - workflow_count: 18, - last_login_at: new Date(Date.now() - 1000 * 60 * 120).toISOString() - }, - { - email: 'automation.expert@tech.com', - first_name: 'David', - last_name: 'Chen', - subscription_plan: 'pro', - workflow_count: 15, - last_login_at: new Date(Date.now() - 1000 * 60 * 45).toISOString() - }, - { - email: 'workflow.master@agency.com', - first_name: 'Emma', - last_name: 'Wilson', - subscription_plan: 'enterprise', - workflow_count: 12, - last_login_at: new Date(Date.now() - 1000 * 60 * 60).toISOString() - } - ], - dailyRegistrations: [ - { date: '2024-09-21', registrations: 3 }, - { date: '2024-09-22', registrations: 5 }, - { date: '2024-09-23', registrations: 2 }, - { date: '2024-09-24', registrations: 8 }, - { date: '2024-09-25', registrations: 4 }, - { date: '2024-09-26', registrations: 6 }, - { date: '2024-09-27', registrations: 7 }, - { date: '2024-09-28', registrations: 9 } - ], - executionTrend: [ - { date: '2024-09-21', executions: 145, successful: 142 }, - { date: '2024-09-22', executions: 167, successful: 163 }, - { date: '2024-09-23', executions: 132, successful: 128 }, - { date: '2024-09-24', executions: 198, successful: 189 }, - { date: '2024-09-25', executions: 156, successful: 151 }, - { date: '2024-09-26', executions: 203, successful: 197 }, - { date: '2024-09-27', executions: 178, successful: 171 }, - { date: '2024-09-28', executions: 234, successful: 227 } - ] - }; - - res.json(analytics); - } catch (error) { - console.error('Analytics error:', error); - res.status(500).json({ error: 'Failed to fetch analytics' }); - } -}); - -// Templates/Workflows endpoint (with /api prefix) -app.get('/api/templates', (req, res) => { - try { - const templates = [ - { - id: 1, - name: "Telegram to Slack Bridge", - description: "Automatically forward messages from Telegram channels to Slack channels with formatting and filtering options", - category: "Communication", - tags: ["telegram", "slack", "messaging", "automation"], - complexity: "intermediate", - estimatedTime: "15 minutes", - useCount: 234, - rating: 4.8, - author: "Aimpress Team", - thumbnail: "/templates/telegram-slack.jpg", - icon: "🔗", - gradient: "from-blue-500 to-purple-600", - workflow: { - nodes: [ - { type: "telegram-trigger", name: "Telegram Webhook" }, - { type: "filter", name: "Message Filter" }, - { type: "slack", name: "Send to Slack" } - ] - }, - createdAt: "2024-08-15T10:30:00Z", - updatedAt: "2024-09-20T14:22:00Z" - }, - { - id: 2, - name: "Gmail to Teams Notifications", - description: "Send important email notifications from Gmail to Microsoft Teams with smart filtering and priority detection", - category: "Email & Notifications", - tags: ["gmail", "teams", "notifications", "email-filter"], - complexity: "beginner", - estimatedTime: "10 minutes", - useCount: 189, - rating: 4.6, - author: "Aimpress Team", - thumbnail: "/templates/gmail-teams.jpg", - icon: "📧", - gradient: "from-red-500 to-blue-600", - workflow: { - nodes: [ - { type: "gmail-trigger", name: "Gmail Watch" }, - { type: "condition", name: "Priority Check" }, - { type: "teams", name: "Teams Message" } - ] - }, - createdAt: "2024-07-22T09:15:00Z", - updatedAt: "2024-09-18T11:45:00Z" - }, - { - id: 3, - name: "Customer Support Automation", - description: "Comprehensive customer support workflow that routes tickets, sends auto-responses, and escalates urgent issues", - category: "Customer Service", - tags: ["support", "automation", "tickets", "escalation"], - complexity: "advanced", - estimatedTime: "45 minutes", - useCount: 156, - rating: 4.9, - author: "Aimpress Team", - thumbnail: "/templates/customer-support.jpg", - icon: "🎧", - gradient: "from-green-500 to-teal-600", - workflow: { - nodes: [ - { type: "webhook", name: "Ticket Webhook" }, - { type: "ai-classifier", name: "Urgency Detection" }, - { type: "condition", name: "Route Decision" }, - { type: "email", name: "Auto Response" }, - { type: "slack", name: "Agent Alert" } - ] - }, - createdAt: "2024-06-10T16:20:00Z", - updatedAt: "2024-09-25T13:30:00Z" - }, - { - id: 4, - name: "Social Media Content Sync", - description: "Automatically sync content across multiple social media platforms with custom formatting for each platform", - category: "Social Media", - tags: ["social-media", "content", "automation", "multi-platform"], - complexity: "intermediate", - estimatedTime: "30 minutes", - useCount: 298, - rating: 4.7, - author: "Aimpress Team", - thumbnail: "/templates/social-sync.jpg", - icon: "📱", - gradient: "from-pink-500 to-orange-600", - workflow: { - nodes: [ - { type: "rss-feed", name: "Content Source" }, - { type: "ai-formatter", name: "Platform Formatter" }, - { type: "twitter", name: "Twitter Post" }, - { type: "linkedin", name: "LinkedIn Post" }, - { type: "facebook", name: "Facebook Post" } - ] - }, - createdAt: "2024-09-01T12:00:00Z", - updatedAt: "2024-09-27T10:15:00Z" - }, - { - id: 5, - name: "E-commerce Order Processing", - description: "Complete order processing pipeline with inventory checks, payment verification, and shipping notifications", - category: "E-commerce", - tags: ["orders", "inventory", "payments", "shipping"], - complexity: "advanced", - estimatedTime: "60 minutes", - useCount: 87, - rating: 4.8, - author: "Aimpress Team", - thumbnail: "/templates/ecommerce-orders.jpg", - icon: "🛒", - gradient: "from-indigo-500 to-purple-600", - workflow: { - nodes: [ - { type: "shopify-trigger", name: "New Order" }, - { type: "inventory-check", name: "Stock Verification" }, - { type: "payment-gateway", name: "Payment Check" }, - { type: "shipping-api", name: "Create Shipment" }, - { type: "email", name: "Customer Notification" } - ] - }, - createdAt: "2024-08-05T14:30:00Z", - updatedAt: "2024-09-22T16:45:00Z" - }, - { - id: 6, - name: "Data Backup & Sync", - description: "Automated data backup solution that syncs files across multiple cloud storage providers with versioning", - category: "Data Management", - tags: ["backup", "sync", "cloud-storage", "versioning"], - complexity: "intermediate", - estimatedTime: "25 minutes", - useCount: 142, - rating: 4.5, - author: "Aimpress Team", - thumbnail: "/templates/data-backup.jpg", - icon: "☁️", - gradient: "from-cyan-500 to-blue-600", - workflow: { - nodes: [ - { type: "schedule", name: "Daily Trigger" }, - { type: "google-drive", name: "Source Files" }, - { type: "dropbox", name: "Backup to Dropbox" }, - { type: "aws-s3", name: "Archive to S3" }, - { type: "slack", name: "Status Report" } - ] - }, - createdAt: "2024-07-15T11:20:00Z", - updatedAt: "2024-09-19T09:30:00Z" - } - ]; - - res.json({ - templates, - categories: ["Communication", "Email & Notifications", "Customer Service", "Social Media", "E-commerce", "Data Management"], - totalCount: templates.length - }); - } catch (error) { - console.error('Templates error:', error); - res.status(500).json({ error: 'Failed to fetch templates' }); - } -}); - -// Templates endpoint (without /api prefix for frontend compatibility) -app.get('/templates', (req, res) => { - try { - const templates = [ - { - id: 1, - name: "Telegram to Slack Bridge", - description: "Automatically forward messages from Telegram channels to Slack channels with formatting and filtering options", - category: "Communication", - tags: ["telegram", "slack", "messaging", "automation"], - complexity: "intermediate", - estimatedTime: "15 minutes", - useCount: 234, - rating: 4.8, - author: "Aimpress Team", - thumbnail: "/templates/telegram-slack.jpg", - icon: "🔗", - gradient: "from-blue-500 to-purple-600", - workflow: { - nodes: [ - { type: "telegram-trigger", name: "Telegram Webhook" }, - { type: "filter", name: "Message Filter" }, - { type: "slack", name: "Send to Slack" } - ] - }, - createdAt: "2024-08-15T10:30:00Z", - updatedAt: "2024-09-20T14:22:00Z" - }, - { - id: 2, - name: "Gmail to Teams Notifications", - description: "Send important email notifications from Gmail to Microsoft Teams with smart filtering and priority detection", - category: "Email & Notifications", - tags: ["gmail", "teams", "notifications", "email-filter"], - complexity: "beginner", - estimatedTime: "10 minutes", - useCount: 189, - rating: 4.6, - author: "Aimpress Team", - thumbnail: "/templates/gmail-teams.jpg", - icon: "📧", - gradient: "from-red-500 to-blue-600", - workflow: { - nodes: [ - { type: "gmail-trigger", name: "Gmail Watch" }, - { type: "condition", name: "Priority Check" }, - { type: "teams", name: "Teams Message" } - ] - }, - createdAt: "2024-07-22T09:15:00Z", - updatedAt: "2024-09-18T11:45:00Z" - }, - { - id: 3, - name: "Customer Support Automation", - description: "Comprehensive customer support workflow that routes tickets, sends auto-responses, and escalates urgent issues", - category: "Customer Service", - tags: ["support", "automation", "tickets", "escalation"], - complexity: "advanced", - estimatedTime: "45 minutes", - useCount: 156, - rating: 4.9, - author: "Aimpress Team", - thumbnail: "/templates/customer-support.jpg", - icon: "🎧", - gradient: "from-green-500 to-teal-600", - workflow: { - nodes: [ - { type: "webhook", name: "Ticket Webhook" }, - { type: "ai-classifier", name: "Urgency Detection" }, - { type: "condition", name: "Route Decision" }, - { type: "email", name: "Auto Response" }, - { type: "slack", name: "Agent Alert" } - ] - }, - createdAt: "2024-06-10T16:20:00Z", - updatedAt: "2024-09-25T13:30:00Z" - }, - { - id: 4, - name: "Social Media Content Sync", - description: "Automatically sync content across multiple social media platforms with custom formatting for each platform", - category: "Social Media", - tags: ["social-media", "content", "automation", "multi-platform"], - complexity: "intermediate", - estimatedTime: "30 minutes", - useCount: 298, - rating: 4.7, - author: "Aimpress Team", - thumbnail: "/templates/social-sync.jpg", - icon: "📱", - gradient: "from-pink-500 to-orange-600", - workflow: { - nodes: [ - { type: "rss-feed", name: "Content Source" }, - { type: "ai-formatter", name: "Platform Formatter" }, - { type: "twitter", name: "Twitter Post" }, - { type: "linkedin", name: "LinkedIn Post" }, - { type: "facebook", name: "Facebook Post" } - ] - }, - createdAt: "2024-09-01T12:00:00Z", - updatedAt: "2024-09-27T10:15:00Z" - }, - { - id: 5, - name: "E-commerce Order Processing", - description: "Complete order processing pipeline with inventory checks, payment verification, and shipping notifications", - category: "E-commerce", - tags: ["orders", "inventory", "payments", "shipping"], - complexity: "advanced", - estimatedTime: "60 minutes", - useCount: 87, - rating: 4.8, - author: "Aimpress Team", - thumbnail: "/templates/ecommerce-orders.jpg", - icon: "🛒", - gradient: "from-indigo-500 to-purple-600", - workflow: { - nodes: [ - { type: "shopify-trigger", name: "New Order" }, - { type: "inventory-check", name: "Stock Verification" }, - { type: "payment-gateway", name: "Payment Check" }, - { type: "shipping-api", name: "Create Shipment" }, - { type: "email", name: "Customer Notification" } - ] - }, - createdAt: "2024-08-05T14:30:00Z", - updatedAt: "2024-09-22T16:45:00Z" - }, - { - id: 6, - name: "Data Backup & Sync", - description: "Automated data backup solution that syncs files across multiple cloud storage providers with versioning", - category: "Data Management", - tags: ["backup", "sync", "cloud-storage", "versioning"], - complexity: "intermediate", - estimatedTime: "25 minutes", - useCount: 142, - rating: 4.5, - author: "Aimpress Team", - thumbnail: "/templates/data-backup.jpg", - icon: "☁️", - gradient: "from-cyan-500 to-blue-600", - workflow: { - nodes: [ - { type: "schedule", name: "Daily Trigger" }, - { type: "google-drive", name: "Source Files" }, - { type: "dropbox", name: "Backup to Dropbox" }, - { type: "aws-s3", name: "Archive to S3" }, - { type: "slack", name: "Status Report" } - ] - }, - createdAt: "2024-07-15T11:20:00Z", - updatedAt: "2024-09-19T09:30:00Z" - } - ]; - - res.json({ - templates, - categories: ["Communication", "Email & Notifications", "Customer Service", "Social Media", "E-commerce", "Data Management"], - totalCount: templates.length - }); - } catch (error) { - console.error('Templates error:', error); - res.status(500).json({ error: 'Failed to fetch templates' }); - } -}); - -// Template installation endpoint -app.post('/templates/:templateId/install', (req, res) => { - try { - const { templateId } = req.params; - const { workflow_name } = req.body; - - console.log(`Installing template ${templateId} with name: ${workflow_name}`); - - // Mock successful installation - res.json({ - success: true, - message: 'Template installed successfully', - workflow: { - id: `workflow_${Date.now()}`, - name: workflow_name, - template_id: templateId, - status: 'active', - created_at: new Date().toISOString() - } - }); - } catch (error) { - console.error('Template installation error:', error); - res.status(500).json({ - success: false, - error: 'Failed to install template' - }); - } -}); - -// Admin Users endpoint -app.get('/admin/users', (req, res) => { - try { - const mockUsers = [ - { - id: '1', - email: 'info@ai-impress.com', - first_name: 'Global', - last_name: 'Admin', - role: 'admin', - subscription_plan: 'enterprise', - subscription_status: 'active', - is_verified: true, - last_login_at: new Date(Date.now() - 1000 * 60 * 10).toISOString(), - created_at: new Date('2024-01-01').toISOString(), - workflow_count: 5 - }, - { - id: '2', - email: 'john.doe@example.com', - first_name: 'John', - last_name: 'Doe', - role: 'pro', - subscription_plan: 'pro', - subscription_status: 'active', - is_verified: true, - last_login_at: new Date(Date.now() - 1000 * 60 * 60).toISOString(), - created_at: new Date('2024-02-15').toISOString(), - workflow_count: 8 - }, - { - id: '3', - email: 'jane.smith@company.com', - first_name: 'Jane', - last_name: 'Smith', - role: 'free', - subscription_plan: 'free', - subscription_status: 'active', - is_verified: true, - last_login_at: new Date(Date.now() - 1000 * 60 * 30).toISOString(), - created_at: new Date('2024-03-10').toISOString(), - workflow_count: 3 - }, - { - id: '4', - email: 'enterprise@bigcorp.com', - first_name: 'Robert', - last_name: 'Johnson', - role: 'enterprise', - subscription_plan: 'enterprise', - subscription_status: 'active', - is_verified: true, - last_login_at: new Date(Date.now() - 1000 * 60 * 120).toISOString(), - created_at: new Date('2024-01-20').toISOString(), - workflow_count: 25 - } - ]; - - res.json({ - users: mockUsers, - pagination: { - currentPage: 1, - totalPages: 1, - totalUsers: mockUsers.length, - limit: 20 - } - }); - } catch (error) { - console.error('Users error:', error); - res.status(500).json({ error: 'Failed to fetch users' }); - } -}); - -// Update user role endpoint -app.patch('/admin/users/:userId/role', (req, res) => { - try { - const { userId } = req.params; - const { role, subscription_plan } = req.body; - - console.log(`Updating user ${userId}: role=${role}, plan=${subscription_plan}`); - - // Mock successful update - res.json({ - id: userId, - email: 'user@example.com', - role, - subscription_plan - }); - } catch (error) { - console.error('Update user role error:', error); - res.status(500).json({ error: 'Failed to update user role' }); - } -}); - -app.listen(PORT, () => { - console.log(`Server running on port ${PORT}`); -}); - -export default app; \ No newline at end of file diff --git a/backend/src/index_backup.ts b/backend/src/index_backup.ts deleted file mode 100644 index f53a7f5..0000000 --- a/backend/src/index_backup.ts +++ /dev/null @@ -1,28 +0,0 @@ -import express from 'express'; -import cors from 'cors'; -import helmet from 'helmet'; -import dotenv from 'dotenv'; - -dotenv.config(); - -const app = express(); -const PORT = process.env.PORT || 3001; - -app.use(helmet()); -app.use(cors()); -app.use(express.json()); - -app.get('/health', (req, res) => { - res.json({ status: 'OK', timestamp: new Date().toISOString() }); -}); - -// Simple test route -app.get('/test', (req, res) => { - res.json({ message: 'Backend is working!' }); -}); - -app.listen(PORT, () => { - console.log(`Server running on port ${PORT}`); -}); - -export default app; \ No newline at end of file diff --git a/backend/src/index_full.ts b/backend/src/index_full.ts deleted file mode 100644 index ca4bac2..0000000 --- a/backend/src/index_full.ts +++ /dev/null @@ -1,45 +0,0 @@ -import express from 'express'; -import cors from 'cors'; -import helmet from 'helmet'; -import dotenv from 'dotenv'; - -// Route imports -import authRoutes from './routes/auth'; -import workflowRoutes from './routes/workflows'; -import templateRoutes from './routes/templates'; -import integrationRoutes from './routes/integrations'; -import webhookRoutes from './routes/webhooks'; -import logRoutes from './routes/logs'; -import chatRoutes from './routes/chat'; -import adminRoutes from './routes/admin'; -import billingRoutes from './routes/billing'; - -dotenv.config(); - -const app = express(); -const PORT = process.env.PORT || 3001; - -app.use(helmet()); -app.use(cors()); -app.use(express.json()); - -app.get('/health', (req, res) => { - res.json({ status: 'OK', timestamp: new Date().toISOString() }); -}); - -// API Routes -app.use('/auth', authRoutes); -app.use('/workflows', workflowRoutes); -app.use('/templates', templateRoutes); -app.use('/integrations', integrationRoutes); -app.use('/webhooks', webhookRoutes); -app.use('/logs', logRoutes); -app.use('/chat', chatRoutes); -app.use('/admin', adminRoutes); -app.use('/billing', billingRoutes); - -app.listen(PORT, () => { - console.log(`Server running on port ${PORT}`); -}); - -export default app; \ No newline at end of file diff --git a/backend/src/middleware/auth.ts b/backend/src/middleware/auth.ts deleted file mode 100644 index 5449e74..0000000 --- a/backend/src/middleware/auth.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { Request, Response, NextFunction } from 'express'; -import { verifyToken } from '../utils/auth'; - -export interface AuthRequest extends Request { - user?: { - id: number; - email: string; - role?: string; - subscription_plan?: string; - }; -} - -export const authenticateToken = (req: AuthRequest, res: Response, next: NextFunction) => { - const authHeader = req.headers['authorization']; - const token = authHeader && authHeader.split(' ')[1]; - - if (!token) { - return res.status(401).json({ success: false, message: 'Access token required' }); - } - - try { - const decoded = verifyToken(token); - req.user = { - id: decoded.userId, - email: decoded.email, - role: decoded.role, - subscription_plan: decoded.subscription_plan - }; - next(); - } catch (error) { - return res.status(403).json({ success: false, message: 'Invalid or expired token' }); - } -}; - -// Alias for consistency -export const auth = authenticateToken; \ No newline at end of file diff --git a/backend/src/routes/admin.ts b/backend/src/routes/admin.ts deleted file mode 100644 index f77106b..0000000 --- a/backend/src/routes/admin.ts +++ /dev/null @@ -1,27 +0,0 @@ -import express from 'express'; -import { auth } from '../middleware/auth'; -import { - getAnalytics, - getAllUsers, - updateUserRole, - getSystemSettings, - updateSystemSetting -} from '../controllers/adminController'; - -const router = express.Router(); - -// All admin routes require authentication -router.use(auth); - -// Analytics -router.get('/analytics', getAnalytics); - -// User management -router.get('/users', getAllUsers); -router.patch('/users/:userId/role', updateUserRole); - -// System settings -router.get('/settings', getSystemSettings); -router.patch('/settings/:key', updateSystemSetting); - -export default router; \ No newline at end of file diff --git a/backend/src/routes/auth.ts b/backend/src/routes/auth.ts deleted file mode 100644 index 085ef15..0000000 --- a/backend/src/routes/auth.ts +++ /dev/null @@ -1,10 +0,0 @@ -import express from 'express'; -import { signup, login, resetPassword } from '../controllers/authController'; - -const router = express.Router(); - -router.post('/signup', signup); -router.post('/login', login); -router.post('/reset-password', resetPassword); - -export default router; \ No newline at end of file diff --git a/backend/src/routes/billing.ts b/backend/src/routes/billing.ts deleted file mode 100644 index 7c0a6a1..0000000 --- a/backend/src/routes/billing.ts +++ /dev/null @@ -1,28 +0,0 @@ -import express from 'express'; -import { auth } from '../middleware/auth'; -import { - getSubscriptionPlans, - getCurrentSubscription, - upgradeSubscription, - cancelSubscription, - getUsageStats, - handlePaymentWebhook, - generateInvoice -} from '../controllers/billingController'; - -const router = express.Router(); - -// Public routes -router.get('/plans', getSubscriptionPlans); -router.post('/webhook', handlePaymentWebhook); // No auth for webhooks - -// Protected routes -router.use(auth); - -router.get('/subscription', getCurrentSubscription); -router.post('/subscription/upgrade', upgradeSubscription); -router.post('/subscription/cancel', cancelSubscription); -router.get('/usage', getUsageStats); -router.get('/invoice/:paymentId', generateInvoice); - -export default router; \ No newline at end of file diff --git a/backend/src/routes/chat.ts b/backend/src/routes/chat.ts deleted file mode 100644 index 32d2fd3..0000000 --- a/backend/src/routes/chat.ts +++ /dev/null @@ -1,11 +0,0 @@ -import express from 'express'; -import { sendMessage, getChatHistory } from '../controllers/chatController'; -import { authenticateToken } from '../middleware/auth'; - -const router = express.Router(); - -router.use(authenticateToken); -router.post('/', sendMessage); -router.get('/history', getChatHistory); - -export default router; \ No newline at end of file diff --git a/backend/src/routes/integrations.ts b/backend/src/routes/integrations.ts deleted file mode 100644 index 53fed2a..0000000 --- a/backend/src/routes/integrations.ts +++ /dev/null @@ -1,12 +0,0 @@ -import express from 'express'; -import { getIntegrations, connectIntegration, disconnectIntegration } from '../controllers/integrationController'; -import { authenticateToken } from '../middleware/auth'; - -const router = express.Router(); - -router.use(authenticateToken); -router.get('/', getIntegrations); -router.post('/:provider/connect', connectIntegration); -router.delete('/:id', disconnectIntegration); - -export default router; \ No newline at end of file diff --git a/backend/src/routes/logs.ts b/backend/src/routes/logs.ts deleted file mode 100644 index bbdb5eb..0000000 --- a/backend/src/routes/logs.ts +++ /dev/null @@ -1,11 +0,0 @@ -import express from 'express'; -import { getWorkflowExecutions, getExecutionDetails } from '../controllers/logController'; -import { authenticateToken } from '../middleware/auth'; - -const router = express.Router(); - -router.use(authenticateToken); -router.get('/', getWorkflowExecutions); -router.get('/:id', getExecutionDetails); - -export default router; \ No newline at end of file diff --git a/backend/src/routes/templates.ts b/backend/src/routes/templates.ts deleted file mode 100644 index 5338712..0000000 --- a/backend/src/routes/templates.ts +++ /dev/null @@ -1,10 +0,0 @@ -import express from 'express'; -import { getTemplates, installTemplate } from '../controllers/templateController'; -import { auth } from '../middleware/auth'; - -const router = express.Router(); - -router.get('/', auth, getTemplates); -router.post('/:id/install', auth, installTemplate); - -export default router; \ No newline at end of file diff --git a/backend/src/routes/webhooks.ts b/backend/src/routes/webhooks.ts deleted file mode 100644 index de5c0bd..0000000 --- a/backend/src/routes/webhooks.ts +++ /dev/null @@ -1,16 +0,0 @@ -import express from 'express'; -import { getWebhooks, createWebhook, getWebhookLogs, deleteWebhook, handleWebhookCall } from '../controllers/webhookController'; -import { authenticateToken } from '../middleware/auth'; - -const router = express.Router(); - -router.use(authenticateToken); -router.get('/', getWebhooks); -router.post('/', createWebhook); -router.get('/:id/logs', getWebhookLogs); -router.delete('/:id', deleteWebhook); - -// Public webhook endpoint -router.post('/webhook/:user_id/:slug', handleWebhookCall); - -export default router; \ No newline at end of file diff --git a/backend/src/routes/workflows.ts b/backend/src/routes/workflows.ts deleted file mode 100644 index d12edd2..0000000 --- a/backend/src/routes/workflows.ts +++ /dev/null @@ -1,34 +0,0 @@ -import express from 'express'; -import { - getWorkflows, - getWorkflow, - createWorkflow, - updateWorkflow, - deleteWorkflow, - activateWorkflow, - deactivateWorkflow, - executeWorkflow, - getWorkflowExecutions -} from '../controllers/workflowController'; -import { authenticateToken } from '../middleware/auth'; - -const router = express.Router(); - -router.use(authenticateToken); - -// Workflow CRUD -router.get('/', getWorkflows); -router.get('/:id', getWorkflow); -router.post('/', createWorkflow); -router.put('/:id', updateWorkflow); -router.delete('/:id', deleteWorkflow); - -// Workflow Actions -router.post('/:id/activate', activateWorkflow); -router.post('/:id/deactivate', deactivateWorkflow); -router.post('/:id/execute', executeWorkflow); - -// Workflow Executions -router.get('/:id/executions', getWorkflowExecutions); - -export default router; \ No newline at end of file diff --git a/backend/src/services/n8nService.ts b/backend/src/services/n8nService.ts deleted file mode 100644 index 303c895..0000000 --- a/backend/src/services/n8nService.ts +++ /dev/null @@ -1,226 +0,0 @@ -import axios, { AxiosInstance } from 'axios'; - -interface N8nConfig { - baseUrl: string; - apiToken: string; -} - -interface WorkflowData { - name: string; - active: boolean; - nodes: any[]; - connections: any; - settings?: any; - staticData?: any; -} - -interface N8nWorkflow { - id: string; - name: string; - active: boolean; - nodes: any[]; - connections: any; - createdAt: string; - updatedAt: string; - settings?: any; - staticData?: any; -} - -interface ExecutionResult { - id: string; - finished: boolean; - mode: string; - startedAt: string; - stoppedAt?: string; - workflowData: any; - data?: any; -} - -class N8nService { - private client: AxiosInstance; - private config: N8nConfig; - - constructor(config: N8nConfig) { - this.config = config; - this.client = axios.create({ - baseURL: `${config.baseUrl}/api/v1`, - headers: { - 'X-N8N-API-KEY': config.apiToken, - 'Content-Type': 'application/json', - }, - timeout: 30000, - }); - - // Add response interceptor for error handling - this.client.interceptors.response.use( - response => response, - error => { - console.error('N8n API Error:', error.response?.data || error.message); - throw error; - } - ); - } - - // Workflow Management - async getWorkflows(): Promise { - try { - const response = await this.client.get('/workflows'); - return response.data.data || response.data; - } catch (error) { - console.error('Failed to fetch workflows:', error); - throw new Error('Failed to fetch workflows from n8n'); - } - } - - async getWorkflow(workflowId: string): Promise { - try { - const response = await this.client.get(`/workflows/${workflowId}`); - return response.data; - } catch (error) { - console.error(`Failed to fetch workflow ${workflowId}:`, error); - throw new Error(`Failed to fetch workflow ${workflowId} from n8n`); - } - } - - async createWorkflow(workflowData: WorkflowData): Promise { - try { - const response = await this.client.post('/workflows', workflowData); - return response.data; - } catch (error) { - console.error('Failed to create workflow:', error); - throw new Error('Failed to create workflow in n8n'); - } - } - - async updateWorkflow(workflowId: string, workflowData: Partial): Promise { - try { - const response = await this.client.patch(`/workflows/${workflowId}`, workflowData); - return response.data; - } catch (error) { - console.error(`Failed to update workflow ${workflowId}:`, error); - throw new Error(`Failed to update workflow ${workflowId} in n8n`); - } - } - - async deleteWorkflow(workflowId: string): Promise { - try { - await this.client.delete(`/workflows/${workflowId}`); - } catch (error) { - console.error(`Failed to delete workflow ${workflowId}:`, error); - throw new Error(`Failed to delete workflow ${workflowId} from n8n`); - } - } - - async activateWorkflow(workflowId: string): Promise { - try { - const response = await this.client.patch(`/workflows/${workflowId}`, { active: true }); - return response.data; - } catch (error) { - console.error(`Failed to activate workflow ${workflowId}:`, error); - throw new Error(`Failed to activate workflow ${workflowId} in n8n`); - } - } - - async deactivateWorkflow(workflowId: string): Promise { - try { - const response = await this.client.patch(`/workflows/${workflowId}`, { active: false }); - return response.data; - } catch (error) { - console.error(`Failed to deactivate workflow ${workflowId}:`, error); - throw new Error(`Failed to deactivate workflow ${workflowId} in n8n`); - } - } - - // Execution Management - async executeWorkflow(workflowId: string, inputData?: any): Promise { - try { - const response = await this.client.post(`/workflows/${workflowId}/execute`, { - ...(inputData && { inputData }) - }); - return response.data; - } catch (error) { - console.error(`Failed to execute workflow ${workflowId}:`, error); - throw new Error(`Failed to execute workflow ${workflowId} in n8n`); - } - } - - async getExecutions(workflowId?: string, limit: number = 20): Promise { - try { - const params: any = { limit }; - if (workflowId) { - params.workflowId = workflowId; - } - - const response = await this.client.get('/executions', { params }); - return response.data.data || response.data; - } catch (error) { - console.error('Failed to fetch executions:', error); - throw new Error('Failed to fetch executions from n8n'); - } - } - - async getExecution(executionId: string): Promise { - try { - const response = await this.client.get(`/executions/${executionId}`); - return response.data; - } catch (error) { - console.error(`Failed to fetch execution ${executionId}:`, error); - throw new Error(`Failed to fetch execution ${executionId} from n8n`); - } - } - - async deleteExecution(executionId: string): Promise { - try { - await this.client.delete(`/executions/${executionId}`); - } catch (error) { - console.error(`Failed to delete execution ${executionId}:`, error); - throw new Error(`Failed to delete execution ${executionId} from n8n`); - } - } - - // Health and Status - async getHealth(): Promise<{ status: string }> { - try { - const response = await this.client.get('/health'); - return response.data; - } catch (error) { - console.error('Failed to check n8n health:', error); - throw new Error('Failed to check n8n health'); - } - } - - // Credentials Management (if needed) - async getCredentials(): Promise { - try { - const response = await this.client.get('/credentials'); - return response.data.data || response.data; - } catch (error) { - console.error('Failed to fetch credentials:', error); - throw new Error('Failed to fetch credentials from n8n'); - } - } - - // Test connection - async testConnection(): Promise { - try { - await this.getHealth(); - return true; - } catch (error) { - return false; - } - } -} - -// Factory function to create n8n service instance -export const createN8nService = (config: N8nConfig): N8nService => { - return new N8nService(config); -}; - -// Default instance using environment variables -export const n8nService = createN8nService({ - baseUrl: process.env.N8N_BASE_URL || 'https://bot.ai-impress.com', - apiToken: process.env.N8N_API_TOKEN || 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1OWQyN2Q0ZS1jNTU3LTQxMDUtYjZmMy05Y2JmM2U5MzU1NWUiLCJpc3MiOiJuOG4iLCJhdWQiOiJwdWJsaWMtYXBpIiwiaWF0IjoxNzU5MDc1NDI4fQ.HCnDOPdq8GcphuPpz1o9871VOLbpMvd7m8C47e2Kq50', -}); - -export default n8nService; -export type { N8nWorkflow, WorkflowData, ExecutionResult, N8nConfig }; \ No newline at end of file diff --git a/backend/src/types/index.ts b/backend/src/types/index.ts deleted file mode 100644 index 8639aa3..0000000 --- a/backend/src/types/index.ts +++ /dev/null @@ -1,35 +0,0 @@ -export interface User { - id: number; - email: string; - password_hash: string; - first_name?: string; - last_name?: string; - is_verified: boolean; - role: string; - verification_token?: string; - reset_password_token?: string; - reset_password_expires?: Date; - subscription_plan: string; - subscription_status: string; - created_at: Date; - updated_at: Date; -} - -export interface LoginRequest { - email: string; - password: string; -} - -export interface SignupRequest { - email: string; - password: string; - first_name?: string; - last_name?: string; -} - -export interface AuthResponse { - success: boolean; - token?: string; - user?: Omit; - message?: string; -} \ No newline at end of file diff --git a/backend/src/utils/auth.ts b/backend/src/utils/auth.ts deleted file mode 100644 index 8c7cd33..0000000 --- a/backend/src/utils/auth.ts +++ /dev/null @@ -1,26 +0,0 @@ -import jwt, { SignOptions } from 'jsonwebtoken'; -import bcrypt from 'bcryptjs'; - -const JWT_SECRET = process.env.JWT_SECRET || 'your_super_secret_jwt_key_change_this'; -const JWT_EXPIRES_IN = process.env.JWT_EXPIRES_IN || '24h'; - -export const hashPassword = async (password: string): Promise => { - const saltRounds = 10; - return bcrypt.hash(password, saltRounds); -}; - -export const comparePassword = async (password: string, hash: string): Promise => { - return bcrypt.compare(password, hash); -}; - -export const generateToken = (payload: object): string => { - return jwt.sign(payload, JWT_SECRET, { expiresIn: '24h' }); -}; - -export const verifyToken = (token: string): any => { - return jwt.verify(token, JWT_SECRET); -}; - -export const generateRandomToken = (): string => { - return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15); -}; \ No newline at end of file diff --git a/backend/src/utils/db.ts b/backend/src/utils/db.ts deleted file mode 100644 index be61aeb..0000000 --- a/backend/src/utils/db.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Pool } from 'pg'; - -const pool = new Pool({ - host: process.env.DB_HOST || 'localhost', - port: parseInt(process.env.DB_PORT || '5432'), - database: process.env.DB_NAME || 'saas_automation', - user: process.env.DB_USER || 'postgres', - password: process.env.DB_PASSWORD || 'password', - max: 10, - idleTimeoutMillis: 30000, - connectionTimeoutMillis: 2000, -}); - -export const query = (text: string, params?: any[]) => { - return pool.query(text, params); -}; - -export default pool; \ No newline at end of file diff --git a/backend/tsconfig.json b/backend/tsconfig.json deleted file mode 100644 index d1b16ac..0000000 --- a/backend/tsconfig.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "module": "commonjs", - "lib": ["ES2020"], - "outDir": "./dist", - "rootDir": "./src", - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true - }, - "include": ["src/**/*"], - "exclude": ["node_modules", "dist"] -} \ No newline at end of file diff --git a/deploy.sh b/deploy.sh deleted file mode 100755 index bbd31bb..0000000 --- a/deploy.sh +++ /dev/null @@ -1,96 +0,0 @@ -#!/bin/bash - -# Скрипт деплоя приложения click-counter на VPS -# Использование: ./deploy.sh [VPS_IP] [SSH_USER] - -set -e - -VPS_IP=${1:-"YOUR_VPS_IP"} -SSH_USER=${2:-"root"} -APP_NAME="click-counter" -REMOTE_PATH="/opt/$APP_NAME" - -echo "🚀 Начинаем деплой $APP_NAME на VPS: $VPS_IP" - -# Проверяем что переданы параметры -if [ "$VPS_IP" = "YOUR_VPS_IP" ]; then - echo "❌ Ошибка: Укажите IP VPS" - echo "Использование: ./deploy.sh [VPS_IP] [SSH_USER]" - exit 1 -fi - -# Создаем архив проекта -echo "📦 Создаем архив проекта..." -tar --exclude='.git' \ - --exclude='node_modules' \ - --exclude='*.log' \ - --exclude='.DS_Store' \ - --exclude='saas-*' \ - --exclude='*.tar.gz' \ - -czf ${APP_NAME}-deploy.tar.gz \ - Dockerfile \ - docker-compose.yml \ - .dockerignore \ - package.json \ - package-lock.json \ - server.js \ - public/ - -echo "✅ Архив создан: ${APP_NAME}-deploy.tar.gz" - -# Загружаем на VPS -echo "⬆️ Загружаем на VPS..." -scp ${APP_NAME}-deploy.tar.gz ${SSH_USER}@${VPS_IP}:/tmp/ - -# Выполняем команды на VPS -echo "🔧 Настраиваем на VPS..." -ssh ${SSH_USER}@${VPS_IP} << EOF - set -e - - # Создаем директорию приложения - mkdir -p $REMOTE_PATH - cd $REMOTE_PATH - - # Останавливаем старый контейнер если есть - if docker ps -q -f name=$APP_NAME > /dev/null; then - echo "🛑 Останавливаем старый контейнер..." - docker-compose down || true - fi - - # Распаковываем новую версию - echo "📂 Распаковываем приложение..." - tar -xzf /tmp/${APP_NAME}-deploy.tar.gz -C $REMOTE_PATH - - # Собираем и запускаем - echo "🏗️ Собираем Docker образ..." - docker-compose build --no-cache - - echo "🚀 Запускаем приложение..." - docker-compose up -d - - # Проверяем статус - sleep 5 - if docker-compose ps | grep -q "Up"; then - echo "✅ Приложение успешно запущено!" - echo "🌐 Доступно по адресу: http://$VPS_IP:3000" - else - echo "❌ Ошибка запуска! Проверьте логи:" - docker-compose logs - exit 1 - fi - - # Очищаем временные файлы - rm -f /tmp/${APP_NAME}-deploy.tar.gz - - echo "🧹 Очищаем старые Docker образы..." - docker image prune -f || true -EOF - -# Очищаем локальный архив -rm -f ${APP_NAME}-deploy.tar.gz - -echo "" -echo "🎉 Деплой завершен успешно!" -echo "🌐 Приложение доступно: http://$VPS_IP:3000" -echo "📊 Проверить статус: ssh $SSH_USER@$VPS_IP 'cd $REMOTE_PATH && docker-compose ps'" -echo "📋 Посмотреть логи: ssh $SSH_USER@$VPS_IP 'cd $REMOTE_PATH && docker-compose logs -f'" \ No newline at end of file diff --git a/frontend/.gitignore b/frontend/.gitignore deleted file mode 100644 index 5ef6a52..0000000 --- a/frontend/.gitignore +++ /dev/null @@ -1,41 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.* -.yarn/* -!.yarn/patches -!.yarn/plugins -!.yarn/releases -!.yarn/versions - -# testing -/coverage - -# next.js -/.next/ -/out/ - -# production -/build - -# misc -.DS_Store -*.pem - -# debug -npm-debug.log* -yarn-debug.log* -yarn-error.log* -.pnpm-debug.log* - -# env files (can opt-in for committing if needed) -.env* - -# vercel -.vercel - -# typescript -*.tsbuildinfo -next-env.d.ts diff --git a/frontend/Dockerfile b/frontend/Dockerfile deleted file mode 100644 index d874449..0000000 --- a/frontend/Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -FROM node:18-alpine - -WORKDIR /app - -# Copy package.json and package-lock.json (if available) -COPY package*.json ./ - -# Install dependencies -RUN npm ci --only=production - -# Copy source code -COPY . . - -# Build the application -RUN npm run build - -# Expose port -EXPOSE 3000 - -# Start the application -CMD ["npm", "start"] \ No newline at end of file diff --git a/frontend/Dockerfile.dev b/frontend/Dockerfile.dev deleted file mode 100644 index 356754e..0000000 --- a/frontend/Dockerfile.dev +++ /dev/null @@ -1,18 +0,0 @@ -FROM node:18-alpine - -WORKDIR /app - -# Copy package.json and package-lock.json -COPY package*.json ./ - -# Install all dependencies (including dev dependencies) -RUN npm install - -# Copy source code -COPY . . - -# Expose port -EXPOSE 3000 - -# Start the application in development mode -CMD ["npm", "run", "dev"] \ No newline at end of file diff --git a/frontend/README.md b/frontend/README.md deleted file mode 100644 index e215bc4..0000000 --- a/frontend/README.md +++ /dev/null @@ -1,36 +0,0 @@ -This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). - -## Getting Started - -First, run the development server: - -```bash -npm run dev -# or -yarn dev -# or -pnpm dev -# or -bun dev -``` - -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. - -This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs deleted file mode 100644 index 719cea2..0000000 --- a/frontend/eslint.config.mjs +++ /dev/null @@ -1,25 +0,0 @@ -import { dirname } from "path"; -import { fileURLToPath } from "url"; -import { FlatCompat } from "@eslint/eslintrc"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); - -const compat = new FlatCompat({ - baseDirectory: __dirname, -}); - -const eslintConfig = [ - ...compat.extends("next/core-web-vitals", "next/typescript"), - { - ignores: [ - "node_modules/**", - ".next/**", - "out/**", - "build/**", - "next-env.d.ts", - ], - }, -]; - -export default eslintConfig; diff --git a/frontend/next.config.ts b/frontend/next.config.ts deleted file mode 100644 index e9ffa30..0000000 --- a/frontend/next.config.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { NextConfig } from "next"; - -const nextConfig: NextConfig = { - /* config options here */ -}; - -export default nextConfig; diff --git a/frontend/package-lock.json b/frontend/package-lock.json deleted file mode 100644 index 9259afc..0000000 --- a/frontend/package-lock.json +++ /dev/null @@ -1,6420 +0,0 @@ -{ - "name": "frontend", - "version": "0.1.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "frontend", - "version": "0.1.0", - "dependencies": { - "@headlessui/react": "^2.2.9", - "@heroicons/react": "^2.2.0", - "axios": "^1.12.2", - "lucide-react": "^0.544.0", - "next": "15.5.4", - "react": "19.1.0", - "react-dom": "19.1.0" - }, - "devDependencies": { - "@eslint/eslintrc": "^3", - "@tailwindcss/postcss": "^4", - "@types/node": "^20", - "@types/react": "^19", - "@types/react-dom": "^19", - "eslint": "^9", - "eslint-config-next": "15.5.4", - "tailwindcss": "^4", - "typescript": "^5" - } - }, - "node_modules/@alloc/quick-lru": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", - "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@emnapi/core": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.5.0.tgz", - "integrity": "sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.1.0", - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.5.0.tgz", - "integrity": "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/wasi-threads": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", - "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", - "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/config-array": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", - "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/object-schema": "^2.1.6", - "debug": "^4.3.1", - "minimatch": "^3.1.2" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/config-helpers": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", - "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/core": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", - "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", - "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/js": { - "version": "9.36.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.36.0.tgz", - "integrity": "sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - } - }, - "node_modules/@eslint/object-schema": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", - "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/plugin-kit": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", - "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/core": "^0.15.2", - "levn": "^0.4.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@floating-ui/core": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz", - "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==", - "license": "MIT", - "dependencies": { - "@floating-ui/utils": "^0.2.10" - } - }, - "node_modules/@floating-ui/dom": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz", - "integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==", - "license": "MIT", - "dependencies": { - "@floating-ui/core": "^1.7.3", - "@floating-ui/utils": "^0.2.10" - } - }, - "node_modules/@floating-ui/react": { - "version": "0.26.28", - "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.28.tgz", - "integrity": "sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw==", - "license": "MIT", - "dependencies": { - "@floating-ui/react-dom": "^2.1.2", - "@floating-ui/utils": "^0.2.8", - "tabbable": "^6.0.0" - }, - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" - } - }, - "node_modules/@floating-ui/react-dom": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.6.tgz", - "integrity": "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==", - "license": "MIT", - "dependencies": { - "@floating-ui/dom": "^1.7.4" - }, - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" - } - }, - "node_modules/@floating-ui/utils": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", - "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", - "license": "MIT" - }, - "node_modules/@headlessui/react": { - "version": "2.2.9", - "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-2.2.9.tgz", - "integrity": "sha512-Mb+Un58gwBn0/yWZfyrCh0TJyurtT+dETj7YHleylHk5od3dv2XqETPGWMyQ5/7sYN7oWdyM1u9MvC0OC8UmzQ==", - "license": "MIT", - "dependencies": { - "@floating-ui/react": "^0.26.16", - "@react-aria/focus": "^3.20.2", - "@react-aria/interactions": "^3.25.0", - "@tanstack/react-virtual": "^3.13.9", - "use-sync-external-store": "^1.5.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "react": "^18 || ^19 || ^19.0.0-rc", - "react-dom": "^18 || ^19 || ^19.0.0-rc" - } - }, - "node_modules/@heroicons/react": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.2.0.tgz", - "integrity": "sha512-LMcepvRaS9LYHJGsF0zzmgKCUim/X3N/DQKc4jepAXJ7l8QxJ1PmxJzqplF2Z3FE4PqBAIGyJAQ/w4B5dsqbtQ==", - "license": "MIT", - "peerDependencies": { - "react": ">= 16 || ^19.0.0-rc" - } - }, - "node_modules/@humanfs/core": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", - "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanfs/node": { - "version": "0.16.7", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", - "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanfs/core": "^0.19.1", - "@humanwhocodes/retry": "^0.4.0" - }, - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/retry": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", - "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@img/colour": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz", - "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@img/sharp-darwin-arm64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.4.tgz", - "integrity": "sha512-sitdlPzDVyvmINUdJle3TNHl+AG9QcwiAMsXmccqsCOMZNIdW2/7S26w0LyU8euiLVzFBL3dXPwVCq/ODnf2vA==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.2.3" - } - }, - "node_modules/@img/sharp-darwin-x64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.4.tgz", - "integrity": "sha512-rZheupWIoa3+SOdF/IcUe1ah4ZDpKBGWcsPX6MT0lYniH9micvIU7HQkYTfrx5Xi8u+YqwLtxC/3vl8TQN6rMg==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.2.3" - } - }, - "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.3.tgz", - "integrity": "sha512-QzWAKo7kpHxbuHqUC28DZ9pIKpSi2ts2OJnoIGI26+HMgq92ZZ4vk8iJd4XsxN+tYfNJxzH6W62X5eTcsBymHw==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.3.tgz", - "integrity": "sha512-Ju+g2xn1E2AKO6YBhxjj+ACcsPQRHT0bhpglxcEf+3uyPY+/gL8veniKoo96335ZaPo03bdDXMv0t+BBFAbmRA==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.3.tgz", - "integrity": "sha512-x1uE93lyP6wEwGvgAIV0gP6zmaL/a0tGzJs/BIDDG0zeBhMnuUPm7ptxGhUbcGs4okDJrk4nxgrmxpib9g6HpA==", - "cpu": [ - "arm" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.3.tgz", - "integrity": "sha512-I4RxkXU90cpufazhGPyVujYwfIm9Nk1QDEmiIsaPwdnm013F7RIceaCc87kAH+oUB1ezqEvC6ga4m7MSlqsJvQ==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-ppc64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.3.tgz", - "integrity": "sha512-Y2T7IsQvJLMCBM+pmPbM3bKT/yYJvVtLJGfCs4Sp95SjvnFIjynbjzsa7dY1fRJX45FTSfDksbTp6AGWudiyCg==", - "cpu": [ - "ppc64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.3.tgz", - "integrity": "sha512-RgWrs/gVU7f+K7P+KeHFaBAJlNkD1nIZuVXdQv6S+fNA6syCcoboNjsV2Pou7zNlVdNQoQUpQTk8SWDHUA3y/w==", - "cpu": [ - "s390x" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.3.tgz", - "integrity": "sha512-3JU7LmR85K6bBiRzSUc/Ff9JBVIFVvq6bomKE0e63UXGeRw2HPVEjoJke1Yx+iU4rL7/7kUjES4dZ/81Qjhyxg==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.3.tgz", - "integrity": "sha512-F9q83RZ8yaCwENw1GieztSfj5msz7GGykG/BA+MOUefvER69K/ubgFHNeSyUu64amHIYKGDs4sRCMzXVj8sEyw==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.3.tgz", - "integrity": "sha512-U5PUY5jbc45ANM6tSJpsgqmBF/VsL6LnxJmIf11kB7J5DctHgqm0SkuXzVWtIY90GnJxKnC/JT251TDnk1fu/g==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-linux-arm": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.4.tgz", - "integrity": "sha512-Xyam4mlqM0KkTHYVSuc6wXRmM7LGN0P12li03jAnZ3EJWZqj83+hi8Y9UxZUbxsgsK1qOEwg7O0Bc0LjqQVtxA==", - "cpu": [ - "arm" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.2.3" - } - }, - "node_modules/@img/sharp-linux-arm64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.4.tgz", - "integrity": "sha512-YXU1F/mN/Wu786tl72CyJjP/Ngl8mGHN1hST4BGl+hiW5jhCnV2uRVTNOcaYPs73NeT/H8Upm3y9582JVuZHrQ==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.2.3" - } - }, - "node_modules/@img/sharp-linux-ppc64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.4.tgz", - "integrity": "sha512-F4PDtF4Cy8L8hXA2p3TO6s4aDt93v+LKmpcYFLAVdkkD3hSxZzee0rh6/+94FpAynsuMpLX5h+LRsSG3rIciUQ==", - "cpu": [ - "ppc64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-ppc64": "1.2.3" - } - }, - "node_modules/@img/sharp-linux-s390x": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.4.tgz", - "integrity": "sha512-qVrZKE9Bsnzy+myf7lFKvng6bQzhNUAYcVORq2P7bDlvmF6u2sCmK2KyEQEBdYk+u3T01pVsPrkj943T1aJAsw==", - "cpu": [ - "s390x" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.2.3" - } - }, - "node_modules/@img/sharp-linux-x64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.4.tgz", - "integrity": "sha512-ZfGtcp2xS51iG79c6Vhw9CWqQC8l2Ot8dygxoDoIQPTat/Ov3qAa8qpxSrtAEAJW+UjTXc4yxCjNfxm4h6Xm2A==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.2.3" - } - }, - "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.4.tgz", - "integrity": "sha512-8hDVvW9eu4yHWnjaOOR8kHVrew1iIX+MUgwxSuH2XyYeNRtLUe4VNioSqbNkB7ZYQJj9rUTT4PyRscyk2PXFKA==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.2.3" - } - }, - "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.4.tgz", - "integrity": "sha512-lU0aA5L8QTlfKjpDCEFOZsTYGn3AEiO6db8W5aQDxj0nQkVrZWmN3ZP9sYKWJdtq3PWPhUNlqehWyXpYDcI9Sg==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.2.3" - } - }, - "node_modules/@img/sharp-wasm32": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.4.tgz", - "integrity": "sha512-33QL6ZO/qpRyG7woB/HUALz28WnTMI2W1jgX3Nu2bypqLIKx/QKMILLJzJjI+SIbvXdG9fUnmrxR7vbi1sTBeA==", - "cpu": [ - "wasm32" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", - "optional": true, - "dependencies": { - "@emnapi/runtime": "^1.5.0" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-arm64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.4.tgz", - "integrity": "sha512-2Q250do/5WXTwxW3zjsEuMSv5sUU4Tq9VThWKlU2EYLm4MB7ZeMwF+SFJutldYODXF6jzc6YEOC+VfX0SZQPqA==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-ia32": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.4.tgz", - "integrity": "sha512-3ZeLue5V82dT92CNL6rsal6I2weKw1cYu+rGKm8fOCCtJTR2gYeUfY3FqUnIJsMUPIH68oS5jmZ0NiJ508YpEw==", - "cpu": [ - "ia32" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-x64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.4.tgz", - "integrity": "sha512-xIyj4wpYs8J18sVN3mSQjwrw7fKUqRw+Z5rnHNCy5fYTxigBz81u5mOMPmFumwjcn8+ld1ppptMBCLic1nz6ig==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@isaacs/fs-minipass": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", - "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.4" - }, - "engines": { - "node": ">=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": { - "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.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.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", - "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "^1.4.3", - "@emnapi/runtime": "^1.4.3", - "@tybys/wasm-util": "^0.10.0" - } - }, - "node_modules/@next/env": { - "version": "15.5.4", - "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.4.tgz", - "integrity": "sha512-27SQhYp5QryzIT5uO8hq99C69eLQ7qkzkDPsk3N+GuS2XgOgoYEeOav7Pf8Tn4drECOVDsDg8oj+/DVy8qQL2A==", - "license": "MIT" - }, - "node_modules/@next/eslint-plugin-next": { - "version": "15.5.4", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.5.4.tgz", - "integrity": "sha512-SR1vhXNNg16T4zffhJ4TS7Xn7eq4NfKfcOsRwea7RIAHrjRpI9ALYbamqIJqkAhowLlERffiwk0FMvTLNdnVtw==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-glob": "3.3.1" - } - }, - "node_modules/@next/swc-darwin-arm64": { - "version": "15.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.4.tgz", - "integrity": "sha512-nopqz+Ov6uvorej8ndRX6HlxCYWCO3AHLfKK2TYvxoSB2scETOcfm/HSS3piPqc3A+MUgyHoqE6je4wnkjfrOA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-darwin-x64": { - "version": "15.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.4.tgz", - "integrity": "sha512-QOTCFq8b09ghfjRJKfb68kU9k2K+2wsC4A67psOiMn849K9ZXgCSRQr0oVHfmKnoqCbEmQWG1f2h1T2vtJJ9mA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-gnu": { - "version": "15.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.4.tgz", - "integrity": "sha512-eRD5zkts6jS3VfE/J0Kt1VxdFqTnMc3QgO5lFE5GKN3KDI/uUpSyK3CjQHmfEkYR4wCOl0R0XrsjpxfWEA++XA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-musl": { - "version": "15.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.4.tgz", - "integrity": "sha512-TOK7iTxmXFc45UrtKqWdZ1shfxuL4tnVAOuuJK4S88rX3oyVV4ZkLjtMT85wQkfBrOOvU55aLty+MV8xmcJR8A==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-gnu": { - "version": "15.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.4.tgz", - "integrity": "sha512-7HKolaj+481FSW/5lL0BcTkA4Ueam9SPYWyN/ib/WGAFZf0DGAN8frNpNZYFHtM4ZstrHZS3LY3vrwlIQfsiMA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-musl": { - "version": "15.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.4.tgz", - "integrity": "sha512-nlQQ6nfgN0nCO/KuyEUwwOdwQIGjOs4WNMjEUtpIQJPR2NUfmGpW2wkJln1d4nJ7oUzd1g4GivH5GoEPBgfsdw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-arm64-msvc": { - "version": "15.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.4.tgz", - "integrity": "sha512-PcR2bN7FlM32XM6eumklmyWLLbu2vs+D7nJX8OAIoWy69Kef8mfiN4e8TUv2KohprwifdpFKPzIP1njuCjD0YA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-x64-msvc": { - "version": "15.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.5.4.tgz", - "integrity": "sha512-1ur2tSHZj8Px/KMAthmuI9FMp/YFusMMGoRNJaRZMOlSkgvLjzosSdQI0cJAKogdHl3qXUQKL9MGaYvKwA7DXg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "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/@nolyfill/is-core-module": { - "version": "1.0.39", - "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", - "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.4.0" - } - }, - "node_modules/@react-aria/focus": { - "version": "3.21.1", - "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.21.1.tgz", - "integrity": "sha512-hmH1IhHlcQ2lSIxmki1biWzMbGgnhdxJUM0MFfzc71Rv6YAzhlx4kX3GYn4VNcjCeb6cdPv4RZ5vunV4kgMZYQ==", - "license": "Apache-2.0", - "dependencies": { - "@react-aria/interactions": "^3.25.5", - "@react-aria/utils": "^3.30.1", - "@react-types/shared": "^3.32.0", - "@swc/helpers": "^0.5.0", - "clsx": "^2.0.0" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", - "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" - } - }, - "node_modules/@react-aria/interactions": { - "version": "3.25.5", - "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.25.5.tgz", - "integrity": "sha512-EweYHOEvMwef/wsiEqV73KurX/OqnmbzKQa2fLxdULbec5+yDj6wVGaRHIzM4NiijIDe+bldEl5DG05CAKOAHA==", - "license": "Apache-2.0", - "dependencies": { - "@react-aria/ssr": "^3.9.10", - "@react-aria/utils": "^3.30.1", - "@react-stately/flags": "^3.1.2", - "@react-types/shared": "^3.32.0", - "@swc/helpers": "^0.5.0" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", - "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" - } - }, - "node_modules/@react-aria/ssr": { - "version": "3.9.10", - "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.10.tgz", - "integrity": "sha512-hvTm77Pf+pMBhuBm760Li0BVIO38jv1IBws1xFm1NoL26PU+fe+FMW5+VZWyANR6nYL65joaJKZqOdTQMkO9IQ==", - "license": "Apache-2.0", - "dependencies": { - "@swc/helpers": "^0.5.0" - }, - "engines": { - "node": ">= 12" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" - } - }, - "node_modules/@react-aria/utils": { - "version": "3.30.1", - "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.30.1.tgz", - "integrity": "sha512-zETcbDd6Vf9GbLndO6RiWJadIZsBU2MMm23rBACXLmpRztkrIqPEb2RVdlLaq1+GklDx0Ii6PfveVjx+8S5U6A==", - "license": "Apache-2.0", - "dependencies": { - "@react-aria/ssr": "^3.9.10", - "@react-stately/flags": "^3.1.2", - "@react-stately/utils": "^3.10.8", - "@react-types/shared": "^3.32.0", - "@swc/helpers": "^0.5.0", - "clsx": "^2.0.0" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", - "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" - } - }, - "node_modules/@react-stately/flags": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@react-stately/flags/-/flags-3.1.2.tgz", - "integrity": "sha512-2HjFcZx1MyQXoPqcBGALwWWmgFVUk2TuKVIQxCbRq7fPyWXIl6VHcakCLurdtYC2Iks7zizvz0Idv48MQ38DWg==", - "license": "Apache-2.0", - "dependencies": { - "@swc/helpers": "^0.5.0" - } - }, - "node_modules/@react-stately/utils": { - "version": "3.10.8", - "resolved": "https://registry.npmjs.org/@react-stately/utils/-/utils-3.10.8.tgz", - "integrity": "sha512-SN3/h7SzRsusVQjQ4v10LaVsDc81jyyR0DD5HnsQitm/I5WDpaSr2nRHtyloPFU48jlql1XX/S04T2DLQM7Y3g==", - "license": "Apache-2.0", - "dependencies": { - "@swc/helpers": "^0.5.0" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" - } - }, - "node_modules/@react-types/shared": { - "version": "3.32.0", - "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.32.0.tgz", - "integrity": "sha512-t+cligIJsZYFMSPFMvsJMjzlzde06tZMOIOFa1OV5Z0BcMowrb2g4mB57j/9nP28iJIRYn10xCniQts+qadrqQ==", - "license": "Apache-2.0", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" - } - }, - "node_modules/@rtsao/scc": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", - "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", - "dev": true, - "license": "MIT" - }, - "node_modules/@rushstack/eslint-patch": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.12.0.tgz", - "integrity": "sha512-5EwMtOqvJMMa3HbmxLlF74e+3/HhwBTMcvt3nqVJgGCozO6hzIPOBlwm8mGVNR9SN2IJpxSnlxczyDjcn7qIyw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@swc/helpers": { - "version": "0.5.15", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", - "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.8.0" - } - }, - "node_modules/@tailwindcss/node": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.13.tgz", - "integrity": "sha512-eq3ouolC1oEFOAvOMOBAmfCIqZBJuvWvvYWh5h5iOYfe1HFC6+GZ6EIL0JdM3/niGRJmnrOc+8gl9/HGUaaptw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/remapping": "^2.3.4", - "enhanced-resolve": "^5.18.3", - "jiti": "^2.5.1", - "lightningcss": "1.30.1", - "magic-string": "^0.30.18", - "source-map-js": "^1.2.1", - "tailwindcss": "4.1.13" - } - }, - "node_modules/@tailwindcss/oxide": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.13.tgz", - "integrity": "sha512-CPgsM1IpGRa880sMbYmG1s4xhAy3xEt1QULgTJGQmZUeNgXFR7s1YxYygmJyBGtou4SyEosGAGEeYqY7R53bIA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "detect-libc": "^2.0.4", - "tar": "^7.4.3" - }, - "engines": { - "node": ">= 10" - }, - "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.1.13", - "@tailwindcss/oxide-darwin-arm64": "4.1.13", - "@tailwindcss/oxide-darwin-x64": "4.1.13", - "@tailwindcss/oxide-freebsd-x64": "4.1.13", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.13", - "@tailwindcss/oxide-linux-arm64-gnu": "4.1.13", - "@tailwindcss/oxide-linux-arm64-musl": "4.1.13", - "@tailwindcss/oxide-linux-x64-gnu": "4.1.13", - "@tailwindcss/oxide-linux-x64-musl": "4.1.13", - "@tailwindcss/oxide-wasm32-wasi": "4.1.13", - "@tailwindcss/oxide-win32-arm64-msvc": "4.1.13", - "@tailwindcss/oxide-win32-x64-msvc": "4.1.13" - } - }, - "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.13.tgz", - "integrity": "sha512-BrpTrVYyejbgGo57yc8ieE+D6VT9GOgnNdmh5Sac6+t0m+v+sKQevpFVpwX3pBrM2qKrQwJ0c5eDbtjouY/+ew==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.13.tgz", - "integrity": "sha512-YP+Jksc4U0KHcu76UhRDHq9bx4qtBftp9ShK/7UGfq0wpaP96YVnnjFnj3ZFrUAjc5iECzODl/Ts0AN7ZPOANQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.13.tgz", - "integrity": "sha512-aAJ3bbwrn/PQHDxCto9sxwQfT30PzyYJFG0u/BWZGeVXi5Hx6uuUOQEI2Fa43qvmUjTRQNZnGqe9t0Zntexeuw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.13.tgz", - "integrity": "sha512-Wt8KvASHwSXhKE/dJLCCWcTSVmBj3xhVhp/aF3RpAhGeZ3sVo7+NTfgiN8Vey/Fi8prRClDs6/f0KXPDTZE6nQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.13.tgz", - "integrity": "sha512-mbVbcAsW3Gkm2MGwA93eLtWrwajz91aXZCNSkGTx/R5eb6KpKD5q8Ueckkh9YNboU8RH7jiv+ol/I7ZyQ9H7Bw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.13.tgz", - "integrity": "sha512-wdtfkmpXiwej/yoAkrCP2DNzRXCALq9NVLgLELgLim1QpSfhQM5+ZxQQF8fkOiEpuNoKLp4nKZ6RC4kmeFH0HQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.13.tgz", - "integrity": "sha512-hZQrmtLdhyqzXHB7mkXfq0IYbxegaqTmfa1p9MBj72WPoDD3oNOh1Lnxf6xZLY9C3OV6qiCYkO1i/LrzEdW2mg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.13.tgz", - "integrity": "sha512-uaZTYWxSXyMWDJZNY1Ul7XkJTCBRFZ5Fo6wtjrgBKzZLoJNrG+WderJwAjPzuNZOnmdrVg260DKwXCFtJ/hWRQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.13.tgz", - "integrity": "sha512-oXiPj5mi4Hdn50v5RdnuuIms0PVPI/EG4fxAfFiIKQh5TgQgX7oSuDWntHW7WNIi/yVLAiS+CRGW4RkoGSSgVQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.13.tgz", - "integrity": "sha512-+LC2nNtPovtrDwBc/nqnIKYh/W2+R69FA0hgoeOn64BdCX522u19ryLh3Vf3F8W49XBcMIxSe665kwy21FkhvA==", - "bundleDependencies": [ - "@napi-rs/wasm-runtime", - "@emnapi/core", - "@emnapi/runtime", - "@tybys/wasm-util", - "@emnapi/wasi-threads", - "tslib" - ], - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "^1.4.5", - "@emnapi/runtime": "^1.4.5", - "@emnapi/wasi-threads": "^1.0.4", - "@napi-rs/wasm-runtime": "^0.2.12", - "@tybys/wasm-util": "^0.10.0", - "tslib": "^2.8.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.13.tgz", - "integrity": "sha512-dziTNeQXtoQ2KBXmrjCxsuPk3F3CQ/yb7ZNZNA+UkNTeiTGgfeh+gH5Pi7mRncVgcPD2xgHvkFCh/MhZWSgyQg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.13.tgz", - "integrity": "sha512-3+LKesjXydTkHk5zXX01b5KMzLV1xl2mcktBJkje7rhFUpUlYJy7IMOLqjIRQncLTa1WZZiFY/foAeB5nmaiTw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/postcss": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.13.tgz", - "integrity": "sha512-HLgx6YSFKJT7rJqh9oJs/TkBFhxuMOfUKSBEPYwV+t78POOBsdQ7crhZLzwcH3T0UyUuOzU/GK5pk5eKr3wCiQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@alloc/quick-lru": "^5.2.0", - "@tailwindcss/node": "4.1.13", - "@tailwindcss/oxide": "4.1.13", - "postcss": "^8.4.41", - "tailwindcss": "4.1.13" - } - }, - "node_modules/@tanstack/react-virtual": { - "version": "3.13.12", - "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.13.12.tgz", - "integrity": "sha512-Gd13QdxPSukP8ZrkbgS2RwoZseTTbQPLnQEn7HY/rqtM+8Zt95f7xKC7N0EsKs7aoz0WzZ+fditZux+F8EzYxA==", - "license": "MIT", - "dependencies": { - "@tanstack/virtual-core": "3.13.12" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/@tanstack/virtual-core": { - "version": "3.13.12", - "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.13.12.tgz", - "integrity": "sha512-1YBOJfRHV4sXUmWsFSf5rQor4Ss82G8dQWLRbnk3GA4jeP8hQt1hxXh0tmflpC0dz3VgEv/1+qwPyLeWkQuPFA==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - } - }, - "node_modules/@tybys/wasm-util": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", - "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "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/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/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "20.19.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.17.tgz", - "integrity": "sha512-gfehUI8N1z92kygssiuWvLiwcbOB3IRktR6hTDgJlXMYh5OvkPSRmgfoBUmfZt+vhwJtX7v1Yw4KvvAf7c5QKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/@types/react": { - "version": "19.1.13", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.13.tgz", - "integrity": "sha512-hHkbU/eoO3EG5/MZkuFSKmYqPbSVk5byPFa3e7y/8TybHiLMACgI8seVYlicwk7H5K/rI2px9xrQp/C+AUDTiQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "csstype": "^3.0.2" - } - }, - "node_modules/@types/react-dom": { - "version": "19.1.9", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.9.tgz", - "integrity": "sha512-qXRuZaOsAdXKFyOhRBg6Lqqc0yay13vN7KrIg4L7N4aaHN68ma9OK3NE1BoDFgFOTfM7zg+3/8+2n8rLUH3OKQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@types/react": "^19.0.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.44.1.tgz", - "integrity": "sha512-molgphGqOBT7t4YKCSkbasmu1tb1MgrZ2szGzHbclF7PNmOkSTQVHy+2jXOSnxvR3+Xe1yySHFZoqMpz3TfQsw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.44.1", - "@typescript-eslint/type-utils": "8.44.1", - "@typescript-eslint/utils": "8.44.1", - "@typescript-eslint/visitor-keys": "8.44.1", - "graphemer": "^1.4.0", - "ignore": "^7.0.0", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.44.1", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.44.1.tgz", - "integrity": "sha512-EHrrEsyhOhxYt8MTg4zTF+DJMuNBzWwgvvOYNj/zm1vnaD/IC5zCXFehZv94Piqa2cRFfXrTFxIvO95L7Qc/cw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/scope-manager": "8.44.1", - "@typescript-eslint/types": "8.44.1", - "@typescript-eslint/typescript-estree": "8.44.1", - "@typescript-eslint/visitor-keys": "8.44.1", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/project-service": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.44.1.tgz", - "integrity": "sha512-ycSa60eGg8GWAkVsKV4E6Nz33h+HjTXbsDT4FILyL8Obk5/mx4tbvCNsLf9zret3ipSumAOG89UcCs/KRaKYrA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.44.1", - "@typescript-eslint/types": "^8.44.1", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.44.1.tgz", - "integrity": "sha512-NdhWHgmynpSvyhchGLXh+w12OMT308Gm25JoRIyTZqEbApiBiQHD/8xgb6LqCWCFcxFtWwaVdFsLPQI3jvhywg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.44.1", - "@typescript-eslint/visitor-keys": "8.44.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.44.1.tgz", - "integrity": "sha512-B5OyACouEjuIvof3o86lRMvyDsFwZm+4fBOqFHccIctYgBjqR3qT39FBYGN87khcgf0ExpdCBeGKpKRhSFTjKQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.44.1.tgz", - "integrity": "sha512-KdEerZqHWXsRNKjF9NYswNISnFzXfXNDfPxoTh7tqohU/PRIbwTmsjGK6V9/RTYWau7NZvfo52lgVk+sJh0K3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.44.1", - "@typescript-eslint/typescript-estree": "8.44.1", - "@typescript-eslint/utils": "8.44.1", - "debug": "^4.3.4", - "ts-api-utils": "^2.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.44.1.tgz", - "integrity": "sha512-Lk7uj7y9uQUOEguiDIDLYLJOrYHQa7oBiURYVFqIpGxclAFQ78f6VUOM8lI2XEuNOKNB7XuvM2+2cMXAoq4ALQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.44.1.tgz", - "integrity": "sha512-qnQJ+mVa7szevdEyvfItbO5Vo+GfZ4/GZWWDRRLjrxYPkhM+6zYB2vRYwCsoJLzqFCdZT4mEqyJoyzkunsZ96A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/project-service": "8.44.1", - "@typescript-eslint/tsconfig-utils": "8.44.1", - "@typescript-eslint/types": "8.44.1", - "@typescript-eslint/visitor-keys": "8.44.1", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^2.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/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/@typescript-eslint/typescript-estree/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/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.44.1.tgz", - "integrity": "sha512-DpX5Fp6edTlocMCwA+mHY8Mra+pPjRZ0TfHkXI8QFelIKcbADQz1LUPNtzOFUriBB2UYqw4Pi9+xV4w9ZczHFg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.44.1", - "@typescript-eslint/types": "8.44.1", - "@typescript-eslint/typescript-estree": "8.44.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.44.1.tgz", - "integrity": "sha512-576+u0QD+Jp3tZzvfRfxon0EA2lzcDt3lhUbsC6Lgzy9x2VR4E+JUiNyGHi5T8vk0TV+fpJ5GLG1JsJuWCaKhw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.44.1", - "eslint-visitor-keys": "^4.2.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@unrs/resolver-binding-android-arm-eabi": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", - "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@unrs/resolver-binding-android-arm64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", - "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@unrs/resolver-binding-darwin-arm64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", - "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@unrs/resolver-binding-darwin-x64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", - "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@unrs/resolver-binding-freebsd-x64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", - "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", - "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", - "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", - "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-arm64-musl": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", - "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", - "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", - "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", - "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", - "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-x64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", - "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-x64-musl": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", - "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-wasm32-wasi": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", - "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@napi-rs/wasm-runtime": "^0.2.11" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", - "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", - "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@unrs/resolver-binding-win32-x64-msvc": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", - "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/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/aria-query": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", - "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">= 0.4" - } - }, - "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==", - "dev": true, - "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-includes": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", - "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.24.0", - "es-object-atoms": "^1.1.1", - "get-intrinsic": "^1.3.0", - "is-string": "^1.1.1", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.findlast": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", - "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", - "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.9", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-shim-unscopables": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", - "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", - "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", - "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3", - "es-errors": "^1.3.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "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==", - "dev": true, - "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/ast-types-flow": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", - "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", - "dev": true, - "license": "MIT" - }, - "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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "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/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==", - "dev": true, - "license": "MIT", - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/axe-core": { - "version": "4.10.3", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.3.tgz", - "integrity": "sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==", - "dev": true, - "license": "MPL-2.0", - "engines": { - "node": ">=4" - } - }, - "node_modules/axios": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz", - "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.4", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/axobject-query": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", - "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">= 0.4" - } - }, - "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/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/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", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001745", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001745.tgz", - "integrity": "sha512-ywt6i8FzvdgrrrGbr1jZVObnVv6adj+0if2/omv9cmR2oiZs30zL4DIyaptKcbOrBdOIc74QTMoJvSE2QHh5UQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chownr": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", - "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/client-only": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", - "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", - "license": "MIT" - }, - "node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/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/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/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true, - "license": "MIT" - }, - "node_modules/damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", - "dev": true, - "license": "BSD-2-Clause" - }, - "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==", - "dev": true, - "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==", - "dev": true, - "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==", - "dev": true, - "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": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/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/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "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/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/detect-libc": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.1.tgz", - "integrity": "sha512-ecqj/sy1jcK1uWrwpR67UhYrIFQ+5WlGxth34WquCbamhFA6hkkwiu37o6J5xCHdo1oixJRfVRw+ywV+Hq/0Aw==", - "devOptional": true, - "license": "Apache-2.0", - "engines": { - "node": ">=8" - } - }, - "node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "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/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/enhanced-resolve": { - "version": "5.18.3", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", - "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/es-abstract": { - "version": "1.24.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", - "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", - "dev": true, - "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-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-iterator-helpers": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz", - "integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.6", - "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.3", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.6", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "internal-slot": "^1.1.0", - "iterator.prototype": "^1.1.4", - "safe-array-concat": "^1.1.3" - }, - "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-shim-unscopables": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", - "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", - "dev": true, - "license": "MIT", - "dependencies": { - "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==", - "dev": true, - "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/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "9.36.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.36.0.tgz", - "integrity": "sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.8.0", - "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.0", - "@eslint/config-helpers": "^0.3.1", - "@eslint/core": "^0.15.2", - "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.36.0", - "@eslint/plugin-kit": "^0.3.5", - "@humanfs/node": "^0.16.6", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.2", - "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.6", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.4.0", - "eslint-visitor-keys": "^4.2.1", - "espree": "^10.4.0", - "esquery": "^1.5.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - }, - "peerDependencies": { - "jiti": "*" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - } - } - }, - "node_modules/eslint-config-next": { - "version": "15.5.4", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.5.4.tgz", - "integrity": "sha512-BzgVVuT3kfJes8i2GHenC1SRJ+W3BTML11lAOYFOOPzrk2xp66jBOAGEFRw+3LkYCln5UzvFsLhojrshb5Zfaw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@next/eslint-plugin-next": "15.5.4", - "@rushstack/eslint-patch": "^1.10.3", - "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", - "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-import-resolver-typescript": "^3.5.2", - "eslint-plugin-import": "^2.31.0", - "eslint-plugin-jsx-a11y": "^6.10.0", - "eslint-plugin-react": "^7.37.0", - "eslint-plugin-react-hooks": "^5.0.0" - }, - "peerDependencies": { - "eslint": "^7.23.0 || ^8.0.0 || ^9.0.0", - "typescript": ">=3.3.1" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-import-resolver-typescript": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz", - "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "@nolyfill/is-core-module": "1.0.39", - "debug": "^4.4.0", - "get-tsconfig": "^4.10.0", - "is-bun-module": "^2.0.0", - "stable-hash": "^0.0.5", - "tinyglobby": "^0.2.13", - "unrs-resolver": "^1.6.2" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint-import-resolver-typescript" - }, - "peerDependencies": { - "eslint": "*", - "eslint-plugin-import": "*", - "eslint-plugin-import-x": "*" - }, - "peerDependenciesMeta": { - "eslint-plugin-import": { - "optional": true - }, - "eslint-plugin-import-x": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", - "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.32.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", - "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@rtsao/scc": "^1.1.0", - "array-includes": "^3.1.9", - "array.prototype.findlastindex": "^1.2.6", - "array.prototype.flat": "^1.3.3", - "array.prototype.flatmap": "^1.3.3", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.12.1", - "hasown": "^2.0.2", - "is-core-module": "^2.16.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "object.groupby": "^1.0.3", - "object.values": "^1.2.1", - "semver": "^6.3.1", - "string.prototype.trimend": "^1.0.9", - "tsconfig-paths": "^3.15.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/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/eslint-plugin-jsx-a11y": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", - "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "aria-query": "^5.3.2", - "array-includes": "^3.1.8", - "array.prototype.flatmap": "^1.3.2", - "ast-types-flow": "^0.0.8", - "axe-core": "^4.10.0", - "axobject-query": "^4.1.0", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "hasown": "^2.0.2", - "jsx-ast-utils": "^3.3.5", - "language-tags": "^1.0.9", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "safe-regex-test": "^1.0.3", - "string.prototype.includes": "^2.0.1" - }, - "engines": { - "node": ">=4.0" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" - } - }, - "node_modules/eslint-plugin-react": { - "version": "7.37.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", - "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-includes": "^3.1.8", - "array.prototype.findlast": "^1.2.5", - "array.prototype.flatmap": "^1.3.3", - "array.prototype.tosorted": "^1.1.4", - "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.2.1", - "estraverse": "^5.3.0", - "hasown": "^2.0.2", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.9", - "object.fromentries": "^2.0.8", - "object.values": "^1.2.1", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.5", - "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.12", - "string.prototype.repeat": "^1.0.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" - } - }, - "node_modules/eslint-plugin-react-hooks": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", - "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" - } - }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/eslint-plugin-react/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/eslint-scope": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", - "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", - "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.15.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/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/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-glob": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", - "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", - "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.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/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/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", - "dev": true, - "license": "ISC" - }, - "node_modules/follow-redirects": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "license": "MIT", - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/for-each": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", - "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/form-data": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/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==", - "dev": true, - "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==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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-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==", - "dev": true, - "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-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/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "dev": true, - "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/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" - }, - "node_modules/has-bigints": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", - "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-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": { - "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==", - "dev": true, - "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/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/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/internal-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", - "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.2", - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "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==", - "dev": true, - "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==", - "dev": true, - "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==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-bigints": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "dev": true, - "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-bun-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", - "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.7.1" - } - }, - "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==", - "dev": true, - "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==", - "dev": true, - "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==", - "dev": true, - "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==", - "dev": true, - "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.0", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", - "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "get-proto": "^1.0.0", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-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==", - "dev": true, - "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==", - "dev": true, - "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==", - "dev": true, - "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==", - "dev": true, - "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==", - "dev": true, - "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==", - "dev": true, - "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==", - "dev": true, - "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==", - "dev": true, - "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==", - "dev": true, - "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==", - "dev": true, - "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==", - "dev": true, - "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==", - "dev": true, - "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==", - "dev": true, - "license": "MIT" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/iterator.prototype": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", - "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.6", - "get-proto": "^1.0.0", - "has-symbols": "^1.1.0", - "set-function-name": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/jiti": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.0.tgz", - "integrity": "sha512-VXe6RjJkBPj0ohtqaO8vSWP3ZhAKo66fKrFNCll4BTcwljPLz03pCbaNKfzGP5MbrCYcbJ7v0nOYYwUzTEIdXQ==", - "dev": true, - "license": "MIT", - "bin": { - "jiti": "lib/jiti-cli.mjs" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/jsx-ast-utils": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", - "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "object.assign": "^4.1.4", - "object.values": "^1.1.6" - }, - "engines": { - "node": ">=4.0" - } - }, - "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/language-subtag-registry": { - "version": "0.3.23", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", - "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/language-tags": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", - "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", - "dev": true, - "license": "MIT", - "dependencies": { - "language-subtag-registry": "^0.3.20" - }, - "engines": { - "node": ">=0.10" - } - }, - "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/lightningcss": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", - "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", - "dev": true, - "license": "MPL-2.0", - "dependencies": { - "detect-libc": "^2.0.3" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "lightningcss-darwin-arm64": "1.30.1", - "lightningcss-darwin-x64": "1.30.1", - "lightningcss-freebsd-x64": "1.30.1", - "lightningcss-linux-arm-gnueabihf": "1.30.1", - "lightningcss-linux-arm64-gnu": "1.30.1", - "lightningcss-linux-arm64-musl": "1.30.1", - "lightningcss-linux-x64-gnu": "1.30.1", - "lightningcss-linux-x64-musl": "1.30.1", - "lightningcss-win32-arm64-msvc": "1.30.1", - "lightningcss-win32-x64-msvc": "1.30.1" - } - }, - "node_modules/lightningcss-darwin-arm64": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz", - "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-darwin-x64": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz", - "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-freebsd-x64": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz", - "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz", - "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz", - "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz", - "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz", - "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-musl": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz", - "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz", - "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz", - "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "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.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/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lucide-react": { - "version": "0.544.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.544.0.tgz", - "integrity": "sha512-t5tS44bqd825zAW45UQxpG2CvcC4urOwn2TrwSH8u+MjeE+1NnWl6QqeQ/6NdjMqdOygyiT9p3Ev0p1NJykxjw==", - "license": "ISC", - "peerDependencies": { - "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/magic-string": { - "version": "0.30.19", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz", - "integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/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/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime-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/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/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/minizlib": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", - "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.1.2" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/napi-postinstall": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.3.tgz", - "integrity": "sha512-uTp172LLXSxuSYHv/kou+f6KW3SMppU9ivthaVTXian9sOt3XM/zHYHpRZiLgQoxeWfYUnslNWQHF1+G71xcow==", - "dev": true, - "license": "MIT", - "bin": { - "napi-postinstall": "lib/cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/napi-postinstall" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "license": "MIT" - }, - "node_modules/next": { - "version": "15.5.4", - "resolved": "https://registry.npmjs.org/next/-/next-15.5.4.tgz", - "integrity": "sha512-xH4Yjhb82sFYQfY3vbkJfgSDgXvBB6a8xPs9i35k6oZJRoQRihZH+4s9Yo2qsWpzBmZ3lPXaJ2KPXLfkvW4LnA==", - "license": "MIT", - "dependencies": { - "@next/env": "15.5.4", - "@swc/helpers": "0.5.15", - "caniuse-lite": "^1.0.30001579", - "postcss": "8.4.31", - "styled-jsx": "5.1.6" - }, - "bin": { - "next": "dist/bin/next" - }, - "engines": { - "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" - }, - "optionalDependencies": { - "@next/swc-darwin-arm64": "15.5.4", - "@next/swc-darwin-x64": "15.5.4", - "@next/swc-linux-arm64-gnu": "15.5.4", - "@next/swc-linux-arm64-musl": "15.5.4", - "@next/swc-linux-x64-gnu": "15.5.4", - "@next/swc-linux-x64-musl": "15.5.4", - "@next/swc-win32-arm64-msvc": "15.5.4", - "@next/swc-win32-x64-msvc": "15.5.4", - "sharp": "^0.34.3" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.1.0", - "@playwright/test": "^1.51.1", - "babel-plugin-react-compiler": "*", - "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", - "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", - "sass": "^1.3.0" - }, - "peerDependenciesMeta": { - "@opentelemetry/api": { - "optional": true - }, - "@playwright/test": { - "optional": true - }, - "babel-plugin-react-compiler": { - "optional": true - }, - "sass": { - "optional": true - } - } - }, - "node_modules/next/node_modules/postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "dev": true, - "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==", - "dev": true, - "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==", - "dev": true, - "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.entries": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", - "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", - "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.groupby": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", - "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.values": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", - "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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/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==", - "dev": true, - "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-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/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/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-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/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, - "license": "MIT", - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "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/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/react": { - "version": "19.1.0", - "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", - "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "19.1.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", - "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", - "license": "MIT", - "dependencies": { - "scheduler": "^0.26.0" - }, - "peerDependencies": { - "react": "^19.1.0" - } - }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true, - "license": "MIT" - }, - "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==", - "dev": true, - "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==", - "dev": true, - "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-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-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/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/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/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==", - "dev": true, - "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-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==", - "dev": true, - "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==", - "dev": true, - "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/scheduler": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", - "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", - "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==", - "devOptional": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "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/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==", - "dev": true, - "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==", - "dev": true, - "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/sharp": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.4.tgz", - "integrity": "sha512-FUH39xp3SBPnxWvd5iib1X8XY7J0K0X7d93sie9CJg2PO8/7gmg89Nve6OjItK53/MlAushNNxteBYfM6DEuoA==", - "hasInstallScript": true, - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@img/colour": "^1.0.0", - "detect-libc": "^2.1.0", - "semver": "^7.7.2" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.34.4", - "@img/sharp-darwin-x64": "0.34.4", - "@img/sharp-libvips-darwin-arm64": "1.2.3", - "@img/sharp-libvips-darwin-x64": "1.2.3", - "@img/sharp-libvips-linux-arm": "1.2.3", - "@img/sharp-libvips-linux-arm64": "1.2.3", - "@img/sharp-libvips-linux-ppc64": "1.2.3", - "@img/sharp-libvips-linux-s390x": "1.2.3", - "@img/sharp-libvips-linux-x64": "1.2.3", - "@img/sharp-libvips-linuxmusl-arm64": "1.2.3", - "@img/sharp-libvips-linuxmusl-x64": "1.2.3", - "@img/sharp-linux-arm": "0.34.4", - "@img/sharp-linux-arm64": "0.34.4", - "@img/sharp-linux-ppc64": "0.34.4", - "@img/sharp-linux-s390x": "0.34.4", - "@img/sharp-linux-x64": "0.34.4", - "@img/sharp-linuxmusl-arm64": "0.34.4", - "@img/sharp-linuxmusl-x64": "0.34.4", - "@img/sharp-wasm32": "0.34.4", - "@img/sharp-win32-arm64": "0.34.4", - "@img/sharp-win32-ia32": "0.34.4", - "@img/sharp-win32-x64": "0.34.4" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stable-hash": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", - "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==", - "dev": true, - "license": "MIT" - }, - "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==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "internal-slot": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/string.prototype.includes": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", - "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/string.prototype.matchall": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", - "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.6", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.6", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "internal-slot": "^1.1.0", - "regexp.prototype.flags": "^1.5.3", - "set-function-name": "^2.0.2", - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.repeat": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", - "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "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==", - "dev": true, - "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==", - "dev": true, - "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==", - "dev": true, - "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": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/styled-jsx": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", - "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", - "license": "MIT", - "dependencies": { - "client-only": "0.0.1" - }, - "engines": { - "node": ">= 12.0.0" - }, - "peerDependencies": { - "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "babel-plugin-macros": { - "optional": true - } - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/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/tabbable": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", - "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==", - "license": "MIT" - }, - "node_modules/tailwindcss": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.13.tgz", - "integrity": "sha512-i+zidfmTqtwquj4hMEwdjshYYgMbOrPzb9a0M3ZgNa0JMoZeFC6bxZvO8yr8ozS6ix2SDz0+mvryPeBs2TFE+w==", - "dev": true, - "license": "MIT" - }, - "node_modules/tapable": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.3.tgz", - "integrity": "sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/tar": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.1.tgz", - "integrity": "sha512-nlGpxf+hv0v7GkWBK2V9spgactGOp0qvfWRxUMjqHyzrt3SgwE48DIv/FhqPHJYLHpgW1opq3nERbz5Anq7n1g==", - "dev": true, - "license": "ISC", - "dependencies": { - "@isaacs/fs-minipass": "^4.0.0", - "chownr": "^3.0.0", - "minipass": "^7.1.2", - "minizlib": "^3.1.0", - "yallist": "^5.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/ts-api-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", - "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.12" - }, - "peerDependencies": { - "typescript": ">=4.8.4" - } - }, - "node_modules/tsconfig-paths": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "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": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "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==", - "dev": true, - "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==", - "dev": true, - "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==", - "dev": true, - "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==", - "dev": true, - "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.9.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", - "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", - "dev": true, - "license": "Apache-2.0", - "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==", - "dev": true, - "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==", - "dev": true, - "license": "MIT" - }, - "node_modules/unrs-resolver": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", - "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "napi-postinstall": "^0.3.0" - }, - "funding": { - "url": "https://opencollective.com/unrs-resolver" - }, - "optionalDependencies": { - "@unrs/resolver-binding-android-arm-eabi": "1.11.1", - "@unrs/resolver-binding-android-arm64": "1.11.1", - "@unrs/resolver-binding-darwin-arm64": "1.11.1", - "@unrs/resolver-binding-darwin-x64": "1.11.1", - "@unrs/resolver-binding-freebsd-x64": "1.11.1", - "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", - "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", - "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", - "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", - "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", - "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-x64-musl": "1.11.1", - "@unrs/resolver-binding-wasm32-wasi": "1.11.1", - "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", - "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", - "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" - } - }, - "node_modules/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/use-sync-external-store": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", - "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", - "license": "MIT", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.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/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==", - "dev": true, - "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==", - "dev": true, - "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==", - "dev": true, - "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.19", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", - "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", - "dev": true, - "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/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/yallist": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", - "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } -} diff --git a/frontend/package.json b/frontend/package.json deleted file mode 100644 index 99ee2d3..0000000 --- a/frontend/package.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "frontend", - "version": "0.1.0", - "private": true, - "scripts": { - "dev": "next dev --turbopack", - "build": "next build --turbopack", - "start": "next start", - "lint": "eslint" - }, - "dependencies": { - "@headlessui/react": "^2.2.9", - "@heroicons/react": "^2.2.0", - "axios": "^1.12.2", - "lucide-react": "^0.544.0", - "next": "15.5.4", - "react": "19.1.0", - "react-dom": "19.1.0" - }, - "devDependencies": { - "@eslint/eslintrc": "^3", - "@tailwindcss/postcss": "^4", - "@types/node": "^20", - "@types/react": "^19", - "@types/react-dom": "^19", - "eslint": "^9", - "eslint-config-next": "15.5.4", - "tailwindcss": "^4", - "typescript": "^5" - } -} diff --git a/frontend/postcss.config.mjs b/frontend/postcss.config.mjs deleted file mode 100644 index c7bcb4b..0000000 --- a/frontend/postcss.config.mjs +++ /dev/null @@ -1,5 +0,0 @@ -const config = { - plugins: ["@tailwindcss/postcss"], -}; - -export default config; diff --git a/frontend/src/app/admin/page.tsx b/frontend/src/app/admin/page.tsx deleted file mode 100644 index 3391227..0000000 --- a/frontend/src/app/admin/page.tsx +++ /dev/null @@ -1,505 +0,0 @@ -'use client'; - -import { useState, useEffect } from 'react'; -import { useAuth } from '@/hooks/useAuth'; -import api from '@/lib/api'; -import { - UsersIcon, - CogIcon, - ChartBarIcon, - CurrencyDollarIcon, - ServerIcon, - ClockIcon, - CheckCircleIcon, - XCircleIcon, - ArrowTrendingUpIcon, - ArrowTrendingDownIcon, - EyeIcon, - PencilIcon, - ShieldCheckIcon, - UserGroupIcon, - BuildingOffice2Icon, - PlayIcon, - PauseIcon, -} from '@heroicons/react/24/outline'; -import { useRouter } from 'next/navigation'; - -interface Analytics { - userStats: { - total_users: number; - free_users: number; - pro_users: number; - enterprise_users: number; - verified_users: number; - active_last_7_days: number; - new_last_30_days: number; - }; - workflowStats: { - total_workflows: number; - active_workflows: number; - new_workflows_30_days: number; - activation_rate: number; - }; - executionStats: { - total_executions: number; - successful_executions: number; - executions_24h: number; - executions_7d: number; - }; - revenueStats: { - total_revenue: number; - revenue_30_days: number; - successful_payments: number; - average_order_value: number; - }; - recentActivity: Array<{ - action: string; - resource_type: string; - created_at: string; - user_email: string; - }>; - topUsers: Array<{ - email: string; - first_name: string; - last_name: string; - subscription_plan: string; - workflow_count: number; - last_login_at: string; - }>; -} - -interface User { - id: string; - email: string; - first_name: string; - last_name: string; - role: string; - subscription_plan: string; - subscription_status: string; - is_verified: boolean; - last_login_at: string; - created_at: string; - workflow_count: number; -} - -export default function AdminDashboard() { - const { user } = useAuth(); - const router = useRouter(); - const [analytics, setAnalytics] = useState(null); - const [users, setUsers] = useState([]); - const [loading, setLoading] = useState(true); - const [usersLoading, setUsersLoading] = useState(false); - const [activeTab, setActiveTab] = useState('overview'); - - useEffect(() => { - if (!user || user.role !== 'admin') { - router.push('/dashboard'); - return; - } - fetchAnalytics(); - }, [user, router]); - - const fetchAnalytics = async () => { - try { - setLoading(true); - const response = await api.get('/admin/analytics'); - setAnalytics(response.data); - } catch (error) { - console.error('Error fetching analytics:', error); - } finally { - setLoading(false); - } - }; - - const fetchUsers = async () => { - try { - setUsersLoading(true); - const response = await api.get('/admin/users?limit=50'); - setUsers(response.data.users); - } catch (error) { - console.error('Error fetching users:', error); - } finally { - setUsersLoading(false); - } - }; - - const updateUserRole = async (userId: string, role: string, subscription_plan: string) => { - try { - await api.patch(`/admin/users/${userId}/role`, { role, subscription_plan }); - fetchUsers(); // Refresh users list - } catch (error) { - console.error('Error updating user role:', error); - } - }; - - const formatDate = (dateString: string) => { - return new Date(dateString).toLocaleDateString('en-US', { - month: 'short', - day: 'numeric', - hour: '2-digit', - minute: '2-digit' - }); - }; - - const formatCurrency = (amount: number) => { - return new Intl.NumberFormat('en-GB', { - style: 'currency', - currency: 'GBP' - }).format(amount); - }; - - const getRoleIcon = (role: string) => { - switch (role) { - case 'admin': - return ; - case 'pro': - return ; - case 'enterprise': - return ; - default: - return ; - } - }; - - const getSubscriptionColor = (plan: string) => { - switch (plan) { - case 'enterprise': - return 'bg-purple-100 text-purple-800 border-purple-200'; - case 'pro': - return 'bg-blue-100 text-blue-800 border-blue-200'; - default: - return 'bg-gray-100 text-gray-800 border-gray-200'; - } - }; - - if (loading) { - return ( -
-
-
- ); - } - - if (!analytics) { - return ( -
-
-
-

Failed to load analytics

- -
-
-
- ); - } - - return ( -
-
- {/* Header */} -
-

Admin Dashboard

-

- Complete system analytics and user management -

-
- - {/* Tab Navigation */} -
-
- - -
-
- - {activeTab === 'overview' && ( - <> - {/* Stats Grid */} -
- {/* User Stats */} -
-
-
- -
- - {analytics.userStats.total_users} - -
-

Total Users

-
-
- Free: {analytics.userStats.free_users} - Pro: {analytics.userStats.pro_users} -
-
- Enterprise: {analytics.userStats.enterprise_users} - Active 7d: {analytics.userStats.active_last_7_days} -
-
-
- - {/* Workflow Stats */} -
-
-
- -
- - {analytics.workflowStats.total_workflows} - -
-

Workflows

-
-
- Active: {analytics.workflowStats.active_workflows} - Rate: {Math.round(analytics.workflowStats.activation_rate)}% -
-
- New (30d): {analytics.workflowStats.new_workflows_30_days} -
-
-
- - {/* Execution Stats */} -
-
-
- -
- - {analytics.executionStats.total_executions} - -
-

Executions

-
-
- Successful: {analytics.executionStats.successful_executions} - 24h: {analytics.executionStats.executions_24h} -
-
- 7d: {analytics.executionStats.executions_7d} -
-
-
- - {/* Revenue Stats */} -
-
-
- -
- - {formatCurrency(analytics.revenueStats.total_revenue || 0)} - -
-

Revenue

-
-
- 30d: {formatCurrency(analytics.revenueStats.revenue_30_days || 0)} - Payments: {analytics.revenueStats.successful_payments} -
-
- AOV: {formatCurrency(analytics.revenueStats.average_order_value || 0)} -
-
-
-
- -
- {/* Recent Activity */} -
-
-

Recent Activity

-
-
-
- {analytics.recentActivity.slice(0, 10).map((activity, index) => ( -
-
-
-

- {activity.action.replace(/_/g, ' ')} {activity.resource_type} -

-

- {activity.user_email} • {formatDate(activity.created_at)} -

-
-
- ))} -
-
-
- - {/* Top Users */} -
-
-

Top Users by Workflows

-
-
-
- {analytics.topUsers.slice(0, 10).map((user, index) => ( -
-
-
- {user.first_name?.charAt(0) || user.email.charAt(0).toUpperCase()} -
-
-

- {user.first_name} {user.last_name} ({user.email}) -

-

- {user.subscription_plan} • Last login: {user.last_login_at ? formatDate(user.last_login_at) : 'Never'} -

-
-
-
-

{user.workflow_count}

-

workflows

-
-
- ))} -
-
-
-
- - )} - - {activeTab === 'users' && ( -
-
-

User Management

-
-
- {usersLoading ? ( -
-
-
- ) : ( -
- - - - - - - - - - - - - {users.map((user) => ( - - - - - - - - - ))} - -
- User - - Role - - Subscription - - Workflows - - Last Login - - Actions -
-
-
- {user.first_name?.charAt(0) || user.email.charAt(0).toUpperCase()} -
-
-
- {user.first_name} {user.last_name} -
-
{user.email}
- {user.is_verified && ( - - )} -
-
-
-
- {getRoleIcon(user.role)} - {user.role} -
-
- - {user.subscription_plan} - - - {user.workflow_count} - - {user.last_login_at ? formatDate(user.last_login_at) : 'Never'} - -
- - -
-
-
- )} -
-
- )} -
-
- ); -} \ No newline at end of file diff --git a/frontend/src/app/billing/page.tsx b/frontend/src/app/billing/page.tsx deleted file mode 100644 index ddf5042..0000000 --- a/frontend/src/app/billing/page.tsx +++ /dev/null @@ -1,474 +0,0 @@ -'use client'; - -import { useState, useEffect } from 'react'; -import { useAuth } from '@/hooks/useAuth'; -import api from '@/lib/api'; -import { - CreditCardIcon, - CheckIcon, - XMarkIcon, - ClockIcon, - ChartBarIcon, - DocumentIcon, - ExclamationTriangleIcon, - SparklesIcon, - UserGroupIcon, - BuildingOffice2Icon, - InformationCircleIcon, -} from '@heroicons/react/24/outline'; - -interface Plan { - id: number; - name: string; - price_monthly: number; - price_yearly: number; - workflow_limit: number; - user_limit: number; - features: any; - is_active: boolean; -} - -interface Subscription { - subscription_plan: string; - subscription_status: string; - subscription_starts_at: string; - subscription_ends_at: string; - workflow_limit: number; - user_limit: number; - features: any; - is_expired: boolean; - days_remaining: number; -} - -interface UsageStats { - limits: { - workflows: number; - teamMembers: number; - executions: number; - }; - usage: { - workflows: number; - teamMembers: number; - executions: number; - }; - percentages: { - workflows: number; - teamMembers: number; - executions: number; - }; -} - -export default function BillingPage() { - const { user } = useAuth(); - const [plans, setPlans] = useState([]); - const [subscription, setSubscription] = useState(null); - const [usage, setUsage] = useState(null); - const [loading, setLoading] = useState(true); - const [upgrading, setUpgrading] = useState(null); - const [billingPeriod, setBillingPeriod] = useState<'monthly' | 'yearly'>('monthly'); - - useEffect(() => { - fetchData(); - }, []); - - const fetchData = async () => { - try { - setLoading(true); - const [plansRes, subscriptionRes, usageRes] = await Promise.all([ - api.get('/billing/plans'), - api.get('/billing/subscription'), - api.get('/billing/usage') - ]); - - setPlans(plansRes.data.plans); - setSubscription(subscriptionRes.data.subscription); - setUsage(usageRes.data); - } catch (error) { - console.error('Error fetching billing data:', error); - } finally { - setLoading(false); - } - }; - - const upgradePlan = async (planName: string) => { - try { - setUpgrading(planName); - await api.post('/billing/subscription/upgrade', { - planName, - paymentMethod: 'manual' // In real app, this would be from payment form - }); - - // Refresh data - await fetchData(); - alert('Subscription upgraded successfully!'); - } catch (error) { - console.error('Error upgrading plan:', error); - alert('Failed to upgrade subscription. Please try again.'); - } finally { - setUpgrading(null); - } - }; - - const cancelSubscription = async () => { - if (!confirm('Are you sure you want to cancel your subscription?')) return; - - try { - await api.post('/billing/subscription/cancel'); - await fetchData(); - alert('Subscription cancelled. You will retain access until the end of your billing period.'); - } catch (error) { - console.error('Error cancelling subscription:', error); - alert('Failed to cancel subscription. Please try again.'); - } - }; - - const formatCurrency = (amount: number) => { - return new Intl.NumberFormat('en-GB', { - style: 'currency', - currency: 'GBP' - }).format(amount); - }; - - const formatDate = (dateString: string) => { - return new Date(dateString).toLocaleDateString('en-US', { - year: 'numeric', - month: 'long', - day: 'numeric' - }); - }; - - const getPlanIcon = (planName: string) => { - switch (planName.toLowerCase()) { - case 'free': - return ; - case 'pro': - return ; - case 'enterprise': - return ; - default: - return ; - } - }; - - const getPlanColor = (planName: string) => { - switch (planName.toLowerCase()) { - case 'free': - return 'from-gray-500 to-gray-600'; - case 'pro': - return 'from-blue-500 to-blue-600'; - case 'enterprise': - return 'from-purple-500 to-purple-600'; - default: - return 'from-gray-500 to-gray-600'; - } - }; - - const getUsageColor = (percentage: number) => { - if (percentage >= 90) return 'bg-red-500'; - if (percentage >= 75) return 'bg-yellow-500'; - return 'bg-green-500'; - }; - - if (loading) { - return ( -
-
-
- ); - } - - return ( -
-
- {/* Header */} -
-

Billing & Subscription

-

- Manage your subscription and billing settings -

-
- -
- {/* Current Subscription & Usage */} -
- {/* Current Plan */} - {subscription && ( -
-

Current Plan

- -
-
- {getPlanIcon(subscription.subscription_plan)} -
-
-

- {subscription.subscription_plan} Plan -

-

- {subscription.subscription_status === 'active' ? 'Active' : 'Cancelled'} -

-
-
- - {subscription.subscription_ends_at && ( -
- {subscription.is_expired ? ( -
- - Subscription Expired -
- ) : ( -
- - - {subscription.days_remaining} days remaining - -
- )} -

- Expires on {formatDate(subscription.subscription_ends_at)} -

-
- )} - - {subscription.subscription_status === 'active' && subscription.subscription_plan !== 'free' && ( - - )} -
- )} - - {/* Usage Stats */} - {usage && ( -
-

Usage This Month

- -
-
-
- Workflows - - {usage.usage.workflows}/{usage.limits.workflows === -1 ? '∞' : usage.limits.workflows} - -
-
-
-
-
- -
-
- Team Members - - {usage.usage.teamMembers}/{usage.limits.teamMembers === -1 ? '∞' : usage.limits.teamMembers} - -
-
-
-
-
- -
-
- Executions - - {usage.usage.executions}/{usage.limits.executions === -1 ? '∞' : usage.limits.executions} - -
-
-
-
-
-
-
- )} -
- - {/* Subscription Plans */} -
-
-
-

Subscription Plans

- -
- - -
-
- -
- {plans.map((plan) => { - const isCurrentPlan = subscription?.subscription_plan === plan.name.toLowerCase(); - const price = billingPeriod === 'yearly' ? plan.price_yearly : plan.price_monthly; - const isFree = plan.name.toLowerCase() === 'free'; - - return ( -
- {isCurrentPlan && ( -
- - Current Plan - -
- )} - -
-
- {getPlanIcon(plan.name)} -
-

{plan.name}

-
- {isFree ? ( - 'Free' - ) : plan.name.toLowerCase() === 'enterprise' ? ( - 'Contact Sales' - ) : ( - <> - {formatCurrency(price)} - - /{billingPeriod === 'yearly' ? 'year' : 'month'} - - - )} -
- {billingPeriod === 'yearly' && !isFree && plan.name.toLowerCase() !== 'enterprise' && ( -

Save 17%

- )} -
- -
-
- - - {plan.workflow_limit === -1 ? 'Unlimited' : plan.workflow_limit} workflows - -
-
- - - {plan.user_limit === -1 ? 'Unlimited' : plan.user_limit} team members - -
-
- - - {plan.features?.execution_limit === -1 ? 'Unlimited' : plan.features?.execution_limit} executions/month - -
-
- {plan.features?.api_access ? ( - - ) : ( - - )} - API Access -
-
- {plan.features?.telegram_notifications ? ( - - ) : ( - - )} - Telegram Notifications -
-
- {plan.features?.premium_templates ? ( - - ) : ( - - )} - Premium Templates -
-
- - {!isCurrentPlan && ( - - )} -
- ); - })} -
- -
-
- -
-

Free Trial Information

-

- All new accounts start with a 7-day free trial of Pro features. No credit card required. - You can upgrade or downgrade at any time. Enterprise customers get priority support and custom integrations. -

-
-
-
-
-
-
-
-
- ); -} \ No newline at end of file diff --git a/frontend/src/app/chat/page.tsx b/frontend/src/app/chat/page.tsx deleted file mode 100644 index 982c6be..0000000 --- a/frontend/src/app/chat/page.tsx +++ /dev/null @@ -1,200 +0,0 @@ -'use client'; - -import { useState, useEffect, useRef } from 'react'; -import api from '@/lib/api'; -import { ChatMessage } from '@/types'; -import { PaperAirplaneIcon } from '@heroicons/react/24/outline'; - -export default function ChatPage() { - const [messages, setMessages] = useState([]); - const [inputMessage, setInputMessage] = useState(''); - const [loading, setLoading] = useState(false); - const [sessionId, setSessionId] = useState(''); - const messagesEndRef = useRef(null); - - useEffect(() => { - fetchChatHistory(); - }, []); - - useEffect(() => { - scrollToBottom(); - }, [messages]); - - const scrollToBottom = () => { - messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); - }; - - const fetchChatHistory = async () => { - try { - const response = await api.get('/chat/history'); - setMessages(response.data.messages || []); - } catch (error) { - console.error('Error fetching chat history:', error); - } - }; - - const sendMessage = async (e: React.FormEvent) => { - e.preventDefault(); - if (!inputMessage.trim() || loading) return; - - const userMessage = inputMessage.trim(); - setInputMessage(''); - setLoading(true); - - // Add user message immediately - const newUserMessage: ChatMessage = { - message_type: 'user', - content: userMessage, - created_at: new Date().toISOString(), - }; - setMessages(prev => [...prev, newUserMessage]); - - try { - const response = await api.post('/chat', { - message: userMessage, - session_id: sessionId, - }); - - const { reply, session_id: returnedSessionId } = response.data; - - if (returnedSessionId && !sessionId) { - setSessionId(returnedSessionId); - } - - // Add assistant response - const assistantMessage: ChatMessage = { - message_type: 'assistant', - content: reply, - created_at: new Date().toISOString(), - }; - setMessages(prev => [...prev, assistantMessage]); - } catch (error: any) { - // Add error message - const errorMessage: ChatMessage = { - message_type: 'assistant', - content: 'Sorry, I encountered an error. Please try again.', - created_at: new Date().toISOString(), - }; - setMessages(prev => [...prev, errorMessage]); - } finally { - setLoading(false); - } - }; - - const suggestedQuestions = [ - 'How do I connect Instagram?', - 'How to create a webhook?', - 'My workflow is not working', - 'How do I view execution logs?', - ]; - - return ( -
- {/* Header */} -
-

AI Assistant

-

- Ask me anything about setting up and managing your automations. -

-
- - {/* Messages */} -
-
- {messages.length === 0 && ( -
-
- 🤖 -
-

- Hi! I'm your automation assistant -

-

- I can help you with setting up integrations, creating workflows, troubleshooting issues, and more. -

-
- {suggestedQuestions.map((question, index) => ( - - ))} -
-
- )} - - {messages.map((message, index) => ( -
-
-

{message.content}

-

- {new Date(message.created_at).toLocaleTimeString()} -

-
-
- ))} - - {loading && ( -
-
-
-
-
-
-
-
- AI is typing... -
-
-
- )} - -
-
-
- - {/* Input */} -
-
-
- setInputMessage(e.target.value)} - placeholder="Type your question here..." - disabled={loading} - className="flex-1 border border-gray-300 rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent disabled:opacity-50" - /> - -
-
-
-
- ); -} \ No newline at end of file diff --git a/frontend/src/app/dashboard/page.tsx b/frontend/src/app/dashboard/page.tsx deleted file mode 100644 index 87efc0f..0000000 --- a/frontend/src/app/dashboard/page.tsx +++ /dev/null @@ -1,317 +0,0 @@ -'use client'; - -import { useState, useEffect } from 'react'; -import { useAuth } from '@/hooks/useAuth'; -import api from '@/lib/api'; -import { Workflow } from '@/types'; -import Link from 'next/link'; -import { - PlusIcon, - PlayIcon, - PauseIcon, - CheckCircleIcon, - XCircleIcon, - ClockIcon, - SparklesIcon, - BoltIcon, - ChartBarIcon, - CogIcon as CogIconHeroicon, - ArrowTrendingUpIcon, - EyeIcon, - PencilIcon, -} from '@heroicons/react/24/outline'; - -export default function DashboardPage() { - const { user } = useAuth(); - const [workflows, setWorkflows] = useState([]); - const [loading, setLoading] = useState(true); - - useEffect(() => { - fetchWorkflows(); - }, []); - - const fetchWorkflows = async () => { - try { - const response = await api.get('/workflows'); - setWorkflows(response.data.workflows || []); - } catch (error) { - console.error('Error fetching workflows:', error); - } finally { - setLoading(false); - } - }; - - const getStatusIcon = (status: string) => { - switch (status) { - case 'active': - return ; - case 'inactive': - return ; - case 'error': - return ; - default: - return ; - } - }; - - const getStatusColor = (status: string) => { - switch (status) { - case 'active': - return 'text-green-700 bg-green-100 border-green-200'; - case 'inactive': - return 'text-gray-700 bg-gray-100 border-gray-200'; - case 'error': - return 'text-red-700 bg-red-100 border-red-200'; - default: - return 'text-yellow-700 bg-yellow-100 border-yellow-200'; - } - }; - - if (loading) { - return ( -
-
-
- ); - } - - return ( -
-
- {/* Header */} -
-
-
-

- Welcome back, {user?.first_name || user?.email?.split('@')[0]}! 👋 -

-

- Here's what's happening with your automations today -

-
- - - Create Workflow - - -
-
- - {/* Stats Cards */} -
-
-
-
-

Total Workflows

-

{workflows.length}

-

+2 this week

-
-
- -
-
-
- -
-
-
-

Active Workflows

-

- {workflows.filter(w => w.is_active).length} -

-

Running smoothly

-
-
- -
-
-
- -
-
-
-

Monthly Executions

-

1,247

-

↗ +18% vs last month

-
-
- -
-
-
- -
-
-
-

Current Plan

-

- {user?.subscription_plan} -

-

Unlimited workflows

-
-
- -
-
-
-
- - {/* Quick Actions */} -
- -
-
- -
-
-

- Browse Templates -

-

- Ready-made automation templates -

-
-
- - - -
-
- -
-
-

- Connect Apps -

-

- Integrate with your favorite tools -

-
-
- - - -
-
- -
-
-

- AI Assistant -

-

- Get help building workflows -

-
-
- -
- - {/* Workflows Section */} -
-
-
-
-

Your Workflows

-

Manage and monitor your automations

-
-
- - - -
-
-
- -
- {workflows.length === 0 ? ( -
-
- -
-

No workflows yet

-

- Get started by creating your first automation workflow. Choose from templates or build from scratch. -

-
- - - Browse Templates - - - - Create From Scratch - -
-
- ) : ( -
- {workflows.map((workflow) => ( -
-
-
-
- {getStatusIcon(workflow.status)} -
-
-

- {workflow.name} -

-

- {workflow.description} -

-
-
- - {workflow.status} - -
- -
-
- - {workflow.trigger_type} - - Last run: 2h ago -
-
- - - - -
-
-
- ))} -
- )} -
-
-
-
- ); -} \ No newline at end of file diff --git a/frontend/src/app/favicon.ico b/frontend/src/app/favicon.ico deleted file mode 100644 index 718d6fea4835ec2d246af9800eddb7ffb276240c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25931 zcmeHv30#a{`}aL_*G&7qml|y<+KVaDM2m#dVr!KsA!#An?kSQM(q<_dDNCpjEux83 zLb9Z^XxbDl(w>%i@8hT6>)&Gu{h#Oeyszu?xtw#Zb1mO{pgX9699l+Qppw7jXaYf~-84xW z)w4x8?=youko|}Vr~(D$UXIbiXABHh`p1?nn8Po~fxRJv}|0e(BPs|G`(TT%kKVJAdg5*Z|x0leQq0 zkdUBvb#>9F()jo|T~kx@OM8$9wzs~t2l;K=woNssA3l6|sx2r3+kdfVW@e^8e*E}v zA1y5{bRi+3Z`uD3{F7LgFJDdvm;nJilkzDku>BwXH(8ItVCXk*-lSJnR?-2UN%hJ){&rlvg`CDTj z)Bzo!3v7Ou#83zEDEFcKt(f1E0~=rqeEbTnMvWR#{+9pg%7G8y>u1OVRUSoox-ovF z2Ydma(;=YuBY(eI|04{hXzZD6_f(v~H;C~y5=DhAC{MMS>2fm~1H_t2$56pc$NH8( z5bH|<)71dV-_oCHIrzrT`2s-5w_+2CM0$95I6X8p^r!gHp+j_gd;9O<1~CEQQGS8) zS9Qh3#p&JM-G8rHekNmKVewU;pJRcTAog68KYo^dRo}(M>36U4Us zfgYWSiHZL3;lpWT=zNAW>Dh#mB!_@Lg%$ms8N-;aPqMn+C2HqZgz&9~Eu z4|Kp<`$q)Uw1R?y(~S>ePdonHxpV1#eSP1B;Ogo+-Pk}6#0GsZZ5!||ev2MGdh}_m z{DeR7?0-1^zVs&`AV6Vt;r3`I`OI_wgs*w=eO%_#7Kepl{B@xiyCANc(l zzIyd4y|c6PXWq9-|KM8(zIk8LPk(>a)zyFWjhT!$HJ$qX1vo@d25W<fvZQ2zUz5WRc(UnFMKHwe1| zWmlB1qdbiA(C0jmnV<}GfbKtmcu^2*P^O?MBLZKt|As~ge8&AAO~2K@zbXelK|4T<{|y4`raF{=72kC2Kn(L4YyenWgrPiv z@^mr$t{#X5VuIMeL!7Ab6_kG$&#&5p*Z{+?5U|TZ`B!7llpVmp@skYz&n^8QfPJzL z0G6K_OJM9x+Wu2gfN45phANGt{7=C>i34CV{Xqlx(fWpeAoj^N0Biu`w+MVcCUyU* zDZuzO0>4Z6fbu^T_arWW5n!E45vX8N=bxTVeFoep_G#VmNlQzAI_KTIc{6>c+04vr zx@W}zE5JNSU>!THJ{J=cqjz+4{L4A{Ob9$ZJ*S1?Ggg3klFp!+Y1@K+pK1DqI|_gq z5ZDXVpge8-cs!o|;K73#YXZ3AShj50wBvuq3NTOZ`M&qtjj#GOFfgExjg8Gn8>Vq5 z`85n+9|!iLCZF5$HJ$Iu($dm?8~-ofu}tEc+-pyke=3!im#6pk_Wo8IA|fJwD&~~F zc16osQ)EBo58U7XDuMexaPRjU@h8tXe%S{fA0NH3vGJFhuyyO!Uyl2^&EOpX{9As0 zWj+P>{@}jxH)8|r;2HdupP!vie{sJ28b&bo!8`D^x}TE$%zXNb^X1p@0PJ86`dZyj z%ce7*{^oo+6%&~I!8hQy-vQ7E)0t0ybH4l%KltWOo~8cO`T=157JqL(oq_rC%ea&4 z2NcTJe-HgFjNg-gZ$6!Y`SMHrlj}Etf7?r!zQTPPSv}{so2e>Fjs1{gzk~LGeesX%r(Lh6rbhSo_n)@@G-FTQy93;l#E)hgP@d_SGvyCp0~o(Y;Ee8{ zdVUDbHm5`2taPUOY^MAGOw*>=s7=Gst=D+p+2yON!0%Hk` zz5mAhyT4lS*T3LS^WSxUy86q&GnoHxzQ6vm8)VS}_zuqG?+3td68_x;etQAdu@sc6 zQJ&5|4(I?~3d-QOAODHpZ=hlSg(lBZ!JZWCtHHSj`0Wh93-Uk)_S%zsJ~aD>{`A0~ z9{AG(e|q3g5B%wYKRxiL2Y$8(4w6bzchKuloQW#e&S3n+P- z8!ds-%f;TJ1>)v)##>gd{PdS2Oc3VaR`fr=`O8QIO(6(N!A?pr5C#6fc~Ge@N%Vvu zaoAX2&(a6eWy_q&UwOhU)|P3J0Qc%OdhzW=F4D|pt0E4osw;%<%Dn58hAWD^XnZD= z>9~H(3bmLtxpF?a7su6J7M*x1By7YSUbxGi)Ot0P77`}P3{)&5Un{KD?`-e?r21!4vTTnN(4Y6Lin?UkSM z`MXCTC1@4A4~mvz%Rh2&EwY))LeoT=*`tMoqcEXI>TZU9WTP#l?uFv+@Dn~b(>xh2 z;>B?;Tz2SR&KVb>vGiBSB`@U7VIWFSo=LDSb9F{GF^DbmWAfpms8Sx9OX4CnBJca3 zlj9(x!dIjN?OG1X4l*imJNvRCk}F%!?SOfiOq5y^mZW)jFL@a|r-@d#f7 z2gmU8L3IZq0ynIws=}~m^#@&C%J6QFo~Mo4V`>v7MI-_!EBMMtb%_M&kvAaN)@ZVw z+`toz&WG#HkWDjnZE!6nk{e-oFdL^$YnbOCN}JC&{$#$O27@|Tn-skXr)2ml2~O!5 zX+gYoxhoc7qoU?C^3~&!U?kRFtnSEecWuH0B0OvLodgUAi}8p1 zrO6RSXHH}DMc$&|?D004DiOVMHV8kXCP@7NKB zgaZq^^O<7PoKEp72kby@W0Z!Y*Ay{&vfg#C&gG@YVR9g?FEocMUi1gSN$+V+ayF45{a zuDZDTN}mS|;BO%gEf}pjBfN2-gIrU#G5~cucA;dokXW89%>AyXJJI z9X4UlIWA|ZYHgbI z5?oFk@A=Ik7lrEQPDH!H+b`7_Y~aDb_qa=B2^Y&Ow41cU=4WDd40dp5(QS-WMN-=Y z9g;6_-JdNU;|6cPwf$ak*aJIcwL@1n$#l~zi{c{EW?T;DaW*E8DYq?Umtz{nJ&w-M zEMyTDrC&9K$d|kZe2#ws6)L=7K+{ zQw{XnV6UC$6-rW0emqm8wJoeZK)wJIcV?dST}Z;G0Arq{dVDu0&4kd%N!3F1*;*pW zR&qUiFzK=@44#QGw7k1`3t_d8&*kBV->O##t|tonFc2YWrL7_eqg+=+k;!F-`^b8> z#KWCE8%u4k@EprxqiV$VmmtiWxDLgnGu$Vs<8rppV5EajBXL4nyyZM$SWVm!wnCj-B!Wjqj5-5dNXukI2$$|Bu3Lrw}z65Lc=1G z^-#WuQOj$hwNGG?*CM_TO8Bg-1+qc>J7k5c51U8g?ZU5n?HYor;~JIjoWH-G>AoUP ztrWWLbRNqIjW#RT*WqZgPJXU7C)VaW5}MiijYbABmzoru6EmQ*N8cVK7a3|aOB#O& zBl8JY2WKfmj;h#Q!pN%9o@VNLv{OUL?rixHwOZuvX7{IJ{(EdPpuVFoQqIOa7giLVkBOKL@^smUA!tZ1CKRK}#SSM)iQHk)*R~?M!qkCruaS!#oIL1c z?J;U~&FfH#*98^G?i}pA{ z9Jg36t4=%6mhY(quYq*vSxptes9qy|7xSlH?G=S@>u>Ebe;|LVhs~@+06N<4CViBk zUiY$thvX;>Tby6z9Y1edAMQaiH zm^r3v#$Q#2T=X>bsY#D%s!bhs^M9PMAcHbCc0FMHV{u-dwlL;a1eJ63v5U*?Q_8JO zT#50!RD619#j_Uf))0ooADz~*9&lN!bBDRUgE>Vud-i5ck%vT=r^yD*^?Mp@Q^v+V zG#-?gKlr}Eeqifb{|So?HM&g91P8|av8hQoCmQXkd?7wIJwb z_^v8bbg`SAn{I*4bH$u(RZ6*xUhuA~hc=8czK8SHEKTzSxgbwi~9(OqJB&gwb^l4+m`k*Q;_?>Y-APi1{k zAHQ)P)G)f|AyjSgcCFps)Fh6Bca*Xznq36!pV6Az&m{O8$wGFD? zY&O*3*J0;_EqM#jh6^gMQKpXV?#1?>$ml1xvh8nSN>-?H=V;nJIwB07YX$e6vLxH( zqYwQ>qxwR(i4f)DLd)-$P>T-no_c!LsN@)8`e;W@)-Hj0>nJ-}Kla4-ZdPJzI&Mce zv)V_j;(3ERN3_@I$N<^|4Lf`B;8n+bX@bHbcZTopEmDI*Jfl)-pFDvo6svPRoo@(x z);_{lY<;);XzT`dBFpRmGrr}z5u1=pC^S-{ce6iXQlLGcItwJ^mZx{m$&DA_oEZ)B{_bYPq-HA zcH8WGoBG(aBU_j)vEy+_71T34@4dmSg!|M8Vf92Zj6WH7Q7t#OHQqWgFE3ARt+%!T z?oLovLVlnf?2c7pTc)~cc^($_8nyKwsN`RA-23ed3sdj(ys%pjjM+9JrctL;dy8a( z@en&CQmnV(()bu|Y%G1-4a(6x{aLytn$T-;(&{QIJB9vMox11U-1HpD@d(QkaJdEb zG{)+6Dos_L+O3NpWo^=gR?evp|CqEG?L&Ut#D*KLaRFOgOEK(Kq1@!EGcTfo+%A&I z=dLbB+d$u{sh?u)xP{PF8L%;YPPW53+@{>5W=Jt#wQpN;0_HYdw1{ksf_XhO4#2F= zyPx6Lx2<92L-;L5PD`zn6zwIH`Jk($?Qw({erA$^bC;q33hv!d!>%wRhj# zal^hk+WGNg;rJtb-EB(?czvOM=H7dl=vblBwAv>}%1@{}mnpUznfq1cE^sgsL0*4I zJ##!*B?=vI_OEVis5o+_IwMIRrpQyT_Sq~ZU%oY7c5JMIADzpD!Upz9h@iWg_>>~j zOLS;wp^i$-E?4<_cp?RiS%Rd?i;f*mOz=~(&3lo<=@(nR!_Rqiprh@weZlL!t#NCc zO!QTcInq|%#>OVgobj{~ixEUec`E25zJ~*DofsQdzIa@5^nOXj2T;8O`l--(QyU^$t?TGY^7#&FQ+2SS3B#qK*k3`ye?8jUYSajE5iBbJls75CCc(m3dk{t?- zopcER9{Z?TC)mk~gpi^kbbu>b-+a{m#8-y2^p$ka4n60w;Sc2}HMf<8JUvhCL0B&Btk)T`ctE$*qNW8L$`7!r^9T+>=<=2qaq-;ll2{`{Rg zc5a0ZUI$oG&j-qVOuKa=*v4aY#IsoM+1|c4Z)<}lEDvy;5huB@1RJPquU2U*U-;gu z=En2m+qjBzR#DEJDO`WU)hdd{Vj%^0V*KoyZ|5lzV87&g_j~NCjwv0uQVqXOb*QrQ zy|Qn`hxx(58c70$E;L(X0uZZ72M1!6oeg)(cdKO ze0gDaTz+ohR-#d)NbAH4x{I(21yjwvBQfmpLu$)|m{XolbgF!pmsqJ#D}(ylp6uC> z{bqtcI#hT#HW=wl7>p!38sKsJ`r8}lt-q%Keqy%u(xk=yiIJiUw6|5IvkS+#?JTBl z8H5(Q?l#wzazujH!8o>1xtn8#_w+397*_cy8!pQGP%K(Ga3pAjsaTbbXJlQF_+m+-UpUUent@xM zg%jqLUExj~o^vQ3Gl*>wh=_gOr2*|U64_iXb+-111aH}$TjeajM+I20xw(((>fej-@CIz4S1pi$(#}P7`4({6QS2CaQS4NPENDp>sAqD z$bH4KGzXGffkJ7R>V>)>tC)uax{UsN*dbeNC*v}#8Y#OWYwL4t$ePR?VTyIs!wea+ z5Urmc)X|^`MG~*dS6pGSbU+gPJoq*^a=_>$n4|P^w$sMBBy@f*Z^Jg6?n5?oId6f{ z$LW4M|4m502z0t7g<#Bx%X;9<=)smFolV&(V^(7Cv2-sxbxopQ!)*#ZRhTBpx1)Fc zNm1T%bONzv6@#|dz(w02AH8OXe>kQ#1FMCzO}2J_mST)+ExmBr9cva-@?;wnmWMOk z{3_~EX_xadgJGv&H@zK_8{(x84`}+c?oSBX*Ge3VdfTt&F}yCpFP?CpW+BE^cWY0^ zb&uBN!Ja3UzYHK-CTyA5=L zEMW{l3Usky#ly=7px648W31UNV@K)&Ub&zP1c7%)`{);I4b0Q<)B}3;NMG2JH=X$U zfIW4)4n9ZM`-yRj67I)YSLDK)qfUJ_ij}a#aZN~9EXrh8eZY2&=uY%2N0UFF7<~%M zsB8=erOWZ>Ct_#^tHZ|*q`H;A)5;ycw*IcmVxi8_0Xk}aJA^ath+E;xg!x+As(M#0=)3!NJR6H&9+zd#iP(m0PIW8$ z1Y^VX`>jm`W!=WpF*{ioM?C9`yOR>@0q=u7o>BP-eSHqCgMDj!2anwH?s%i2p+Q7D zzszIf5XJpE)IG4;d_(La-xenmF(tgAxK`Y4sQ}BSJEPs6N_U2vI{8=0C_F?@7<(G; zo$~G=8p+076G;`}>{MQ>t>7cm=zGtfbdDXm6||jUU|?X?CaE?(<6bKDYKeHlz}DA8 zXT={X=yp_R;HfJ9h%?eWvQ!dRgz&Su*JfNt!Wu>|XfU&68iRikRrHRW|ZxzRR^`eIGt zIeiDgVS>IeExKVRWW8-=A=yA`}`)ZkWBrZD`hpWIxBGkh&f#ijr449~m`j6{4jiJ*C!oVA8ZC?$1RM#K(_b zL9TW)kN*Y4%^-qPpMP7d4)o?Nk#>aoYHT(*g)qmRUb?**F@pnNiy6Fv9rEiUqD(^O zzyS?nBrX63BTRYduaG(0VVG2yJRe%o&rVrLjbxTaAFTd8s;<<@Qs>u(<193R8>}2_ zuwp{7;H2a*X7_jryzriZXMg?bTuegABb^87@SsKkr2)0Gyiax8KQWstw^v#ix45EVrcEhr>!NMhprl$InQMzjSFH54x5k9qHc`@9uKQzvL4ihcq{^B zPrVR=o_ic%Y>6&rMN)hTZsI7I<3&`#(nl+3y3ys9A~&^=4?PL&nd8)`OfG#n zwAMN$1&>K++c{^|7<4P=2y(B{jJsQ0a#U;HTo4ZmWZYvI{+s;Td{Yzem%0*k#)vjpB zia;J&>}ICate44SFYY3vEelqStQWFihx%^vQ@Do(sOy7yR2@WNv7Y9I^yL=nZr3mb zXKV5t@=?-Sk|b{XMhA7ZGB@2hqsx}4xwCW!in#C zI@}scZlr3-NFJ@NFaJlhyfcw{k^vvtGl`N9xSo**rDW4S}i zM9{fMPWo%4wYDG~BZ18BD+}h|GQKc-g^{++3MY>}W_uq7jGHx{mwE9fZiPCoxN$+7 zrODGGJrOkcPQUB(FD5aoS4g~7#6NR^ma7-!>mHuJfY5kTe6PpNNKC9GGRiu^L31uG z$7v`*JknQHsYB!Tm_W{a32TM099djW%5e+j0Ve_ct}IM>XLF1Ap+YvcrLV=|CKo6S zb+9Nl3_YdKP6%Cxy@6TxZ>;4&nTneadr z_ES90ydCev)LV!dN=#(*f}|ZORFdvkYBni^aLbUk>BajeWIOcmHP#8S)*2U~QKI%S zyrLmtPqb&TphJ;>yAxri#;{uyk`JJqODDw%(Z=2`1uc}br^V%>j!gS)D*q*f_-qf8&D;W1dJgQMlaH5er zN2U<%Smb7==vE}dDI8K7cKz!vs^73o9f>2sgiTzWcwY|BMYHH5%Vn7#kiw&eItCqa zIkR2~Q}>X=Ar8W|^Ms41Fm8o6IB2_j60eOeBB1Br!boW7JnoeX6Gs)?7rW0^5psc- zjS16yb>dFn>KPOF;imD}e!enuIniFzv}n$m2#gCCv4jM#ArwlzZ$7@9&XkFxZ4n!V zj3dyiwW4Ki2QG{@i>yuZXQizw_OkZI^-3otXC{!(lUpJF33gI60ak;Uqitp74|B6I zgg{b=Iz}WkhCGj1M=hu4#Aw173YxIVbISaoc z-nLZC*6Tgivd5V`K%GxhBsp@SUU60-rfc$=wb>zdJzXS&-5(NRRodFk;Kxk!S(O(a0e7oY=E( zAyS;Ow?6Q&XA+cnkCb{28_1N8H#?J!*$MmIwLq^*T_9-z^&UE@A(z9oGYtFy6EZef LrJugUA?W`A8`#=m diff --git a/frontend/src/app/globals.css b/frontend/src/app/globals.css deleted file mode 100644 index 8e94523..0000000 --- a/frontend/src/app/globals.css +++ /dev/null @@ -1,128 +0,0 @@ -@import "tailwindcss"; - -:root { - /* n8n.io inspired color palette */ - --background: #f8f9fa; - --foreground: #2f3349; - --card: #ffffff; - --card-foreground: #2f3349; - --primary: #ff6d5a; - --primary-foreground: #ffffff; - --secondary: #5865f2; - --secondary-foreground: #ffffff; - --accent: #00d4aa; - --accent-foreground: #ffffff; - --muted: #f1f3f5; - --muted-foreground: #6c757d; - --border: #e5e9f0; - --input: #ffffff; - --ring: #ff6d5a; - - /* Success, warning, error colors in n8n style */ - --success: #00d4aa; - --warning: #ffb800; - --error: #ff4757; - - /* Gradient colors for modern look */ - --gradient-start: #ff6d5a; - --gradient-end: #5865f2; -} - -@theme inline { - --color-background: var(--background); - --color-foreground: var(--foreground); - --color-card: var(--card); - --color-card-foreground: var(--card-foreground); - --color-primary: var(--primary); - --color-primary-foreground: var(--primary-foreground); - --color-secondary: var(--secondary); - --color-secondary-foreground: var(--secondary-foreground); - --color-accent: var(--accent); - --color-accent-foreground: var(--accent-foreground); - --color-muted: var(--muted); - --color-muted-foreground: var(--muted-foreground); - --color-border: var(--border); - --color-input: var(--input); - --color-ring: var(--ring); - --color-success: var(--success); - --color-warning: var(--warning); - --color-error: var(--error); - --font-sans: var(--font-geist-sans); - --font-mono: var(--font-geist-mono); -} - -@media (prefers-color-scheme: dark) { - :root { - --background: #1e1e2e; - --foreground: #cdd6f4; - --card: #282a36; - --card-foreground: #cdd6f4; - --primary: #ff6d5a; - --primary-foreground: #ffffff; - --secondary: #5865f2; - --secondary-foreground: #ffffff; - --accent: #00d4aa; - --accent-foreground: #ffffff; - --muted: #383a59; - --muted-foreground: #9399b2; - --border: #44475a; - --input: #282a36; - --ring: #ff6d5a; - } -} - -body { - background: var(--background); - color: var(--foreground); - font-family: var(--font-sans), -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; - line-height: 1.6; -} - -/* Custom gradients and animations */ -.gradient-primary { - background: linear-gradient(135deg, var(--gradient-start) 0%, var(--gradient-end) 100%); -} - -.gradient-text { - background: linear-gradient(135deg, var(--gradient-start) 0%, var(--gradient-end) 100%); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - background-clip: text; -} - -.animate-float { - animation: float 6s ease-in-out infinite; -} - -@keyframes float { - 0%, 100% { - transform: translateY(0px); - } - 50% { - transform: translateY(-20px); - } -} - -.glass-effect { - backdrop-filter: blur(10px); - background: rgba(255, 255, 255, 0.1); - border: 1px solid rgba(255, 255, 255, 0.2); -} - -/* Custom scrollbar */ -::-webkit-scrollbar { - width: 6px; -} - -::-webkit-scrollbar-track { - background: var(--muted); -} - -::-webkit-scrollbar-thumb { - background: var(--primary); - border-radius: 3px; -} - -::-webkit-scrollbar-thumb:hover { - background: var(--secondary); -} diff --git a/frontend/src/app/integrations/page.tsx b/frontend/src/app/integrations/page.tsx deleted file mode 100644 index 2ba0180..0000000 --- a/frontend/src/app/integrations/page.tsx +++ /dev/null @@ -1,334 +0,0 @@ -'use client'; - -import { useState, useEffect } from 'react'; -import api from '@/lib/api'; -import { Integration } from '@/types'; -import { - LinkIcon, - CheckCircleIcon, - XCircleIcon, - SparklesIcon, - BoltIcon, - ChatBubbleLeftIcon, - EnvelopeIcon, - UserGroupIcon, - BuildingOfficeIcon, - GlobeAltIcon, - CameraIcon, - ShoppingBagIcon, - CalendarIcon -} from '@heroicons/react/24/outline'; - -const availableProviders = [ - { - id: 'gmail', - name: 'Gmail', - description: 'Access your Gmail inbox, send emails, and automate email workflows', - icon: EnvelopeIcon, - color: 'from-red-500 to-red-600', - category: 'Email' - }, - { - id: 'slack', - name: 'Slack', - description: 'Send messages, notifications, and manage team communications', - icon: ChatBubbleLeftIcon, - color: 'from-purple-500 to-purple-600', - category: 'Communication' - }, - { - id: 'telegram', - name: 'Telegram', - description: 'Send messages to channels and groups, manage bots', - icon: ChatBubbleLeftIcon, - color: 'from-blue-500 to-blue-600', - category: 'Communication' - }, - { - id: 'teams', - name: 'Microsoft Teams', - description: 'Collaborate with your team and automate meeting workflows', - icon: UserGroupIcon, - color: 'from-blue-600 to-indigo-600', - category: 'Communication' - }, - { - id: 'instagram', - name: 'Instagram', - description: 'Manage your Instagram business account and automate posts', - icon: CameraIcon, - color: 'from-pink-500 to-purple-600', - category: 'Social Media' - }, - { - id: 'linkedin', - name: 'LinkedIn', - description: 'Manage your LinkedIn connections, posts, and professional network', - icon: UserGroupIcon, - color: 'from-blue-700 to-blue-800', - category: 'Social Media' - }, - { - id: 'shopify', - name: 'Shopify', - description: 'Automate your e-commerce store operations and order processing', - icon: ShoppingBagIcon, - color: 'from-green-500 to-green-600', - category: 'E-commerce' - }, - { - id: 'zoho', - name: 'Zoho CRM', - description: 'Sync contacts, deals, and automate your customer relationship workflows', - icon: BuildingOfficeIcon, - color: 'from-orange-500 to-red-600', - category: 'CRM' - }, - { - id: 'calendly', - name: 'Calendly', - description: 'Automate scheduling and meeting management workflows', - icon: CalendarIcon, - color: 'from-blue-500 to-cyan-600', - category: 'Productivity' - }, - { - id: 'webhook', - name: 'Webhooks', - description: 'Connect any service with custom HTTP webhooks and API calls', - icon: GlobeAltIcon, - color: 'from-gray-500 to-gray-600', - category: 'Developer' - } -]; - -export default function IntegrationsPage() { - const [integrations, setIntegrations] = useState([]); - const [loading, setLoading] = useState(true); - const [connecting, setConnecting] = useState(null); - - useEffect(() => { - fetchIntegrations(); - }, []); - - const fetchIntegrations = async () => { - try { - const response = await api.get('/integrations'); - setIntegrations(response.data.integrations || []); - } catch (error) { - console.error('Error fetching integrations:', error); - } finally { - setLoading(false); - } - }; - - const connectProvider = async (providerId: string) => { - setConnecting(providerId); - try { - // Mock OAuth flow - in real implementation, this would redirect to OAuth provider - const mockToken = 'mock_access_token_' + Math.random().toString(36).substring(7); - - await api.post(`/integrations/${providerId}/connect`, { - access_token: mockToken, - account_name: `Mock ${providerId} Account`, - account_email: `user@${providerId}.com`, - scopes: ['read', 'write'] - }); - - await fetchIntegrations(); - } catch (error: any) { - alert(error.response?.data?.message || 'Failed to connect integration'); - } finally { - setConnecting(null); - } - }; - - const disconnectIntegration = async (integrationId: number) => { - if (!confirm('Are you sure you want to disconnect this integration?')) return; - - try { - await api.delete(`/integrations/${integrationId}`); - await fetchIntegrations(); - } catch (error: any) { - alert(error.response?.data?.message || 'Failed to disconnect integration'); - } - }; - - const getConnectedIntegration = (providerId: string) => { - return integrations.find(int => int.provider === providerId); - }; - - if (loading) { - return ( -
-
-
- ); - } - - const categories = [...new Set(availableProviders.map(p => p.category))]; - - return ( -
-
-
-

Integrations

-

- Connect your favorite apps and services to create powerful automation workflows. -

-
- - {/* Categories Overview */} -
- {categories.map((category) => { - const categoryCount = availableProviders.filter(p => p.category === category).length; - return ( -
-
- -
-

{category}

-

{categoryCount} apps

-
- ); - })} -
- - {/* Integrations Grid */} -
- {availableProviders.map((provider) => { - const connectedIntegration = getConnectedIntegration(provider.id); - const isConnected = !!connectedIntegration; - const IconComponent = provider.icon; - - return ( -
- {/* Header */} -
-
-
-
- -
-
-

- {provider.name} -

- - {provider.category} - -
-
-
- {isConnected ? ( - <> - - Connected - - ) : ( - <> - - Available - - )} -
-
- -

- {provider.description} -

-
- - {/* Footer */} -
- {isConnected ? ( -
-
-
-

- - Connected as: -

-

{connectedIntegration.account_name}

-

- Connected on {new Date(connectedIntegration.created_at).toLocaleDateString()} -

-
-
- -
- ) : ( - - )} -
-
- ); - })} -
- - {/* Info Section */} -
-
-
- -
-

Ready to Automate?

-

- Connect your apps and start building powerful automation workflows in minutes. - No coding required – just point, click, and automate! -

-
-
-
- -
-

Easy Setup

-

Connect in seconds with OAuth authentication

-
-
-
- -
-

Secure

-

Enterprise-grade security for all connections

-
-
-
- -
-

Powerful

-

Create complex workflows with simple drag & drop

-
-
-
-
-
-
- ); -} \ No newline at end of file diff --git a/frontend/src/app/layout.tsx b/frontend/src/app/layout.tsx deleted file mode 100644 index f61880e..0000000 --- a/frontend/src/app/layout.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import type { Metadata } from "next"; -import { Geist, Geist_Mono } from "next/font/google"; -import "./globals.css"; -import ClientProvider from "@/components/ClientProvider"; -import Layout from "@/components/Layout"; - -const geistSans = Geist({ - variable: "--font-geist-sans", - subsets: ["latin"], -}); - -const geistMono = Geist_Mono({ - variable: "--font-geist-mono", - subsets: ["latin"], -}); - -export const metadata: Metadata = { - title: "Aimpress AutomationHub - SaaS Automation Platform", - description: "Build and manage your automation workflows with ease", -}; - -export default function RootLayout({ - children, -}: Readonly<{ - children: React.ReactNode; -}>) { - return ( - - - - {children} - - - - ); -} diff --git a/frontend/src/app/login/page.tsx b/frontend/src/app/login/page.tsx deleted file mode 100644 index 15b9bbb..0000000 --- a/frontend/src/app/login/page.tsx +++ /dev/null @@ -1,206 +0,0 @@ -'use client'; - -import { useState } from 'react'; -import { useAuth } from '@/hooks/useAuth'; -import Link from 'next/link'; -import { useRouter } from 'next/navigation'; -import { EyeIcon, EyeSlashIcon, BoltIcon, ArrowRightIcon } from '@heroicons/react/24/outline'; - -export default function LoginPage() { - const [email, setEmail] = useState(''); - const [password, setPassword] = useState(''); - const [showPassword, setShowPassword] = useState(false); - const [loading, setLoading] = useState(false); - const [error, setError] = useState(''); - const { login } = useAuth(); - const router = useRouter(); - - const handleSubmit = async (e: React.FormEvent) => { - e.preventDefault(); - setLoading(true); - setError(''); - - try { - await login(email, password); - router.push('/dashboard'); - } catch (err: any) { - setError(err.message); - } finally { - setLoading(false); - } - }; - - return ( -
-
- {/* Logo and Back to Home */} -
- - - Back to Home - -
-
- -
- AutomationHub -
-

- Welcome back -

-

- Sign in to continue building amazing automations -

-
- - {/* Login Form */} -
-
- {error && ( -
- {error} -
- )} - -
-
- - setEmail(e.target.value)} - className="w-full px-4 py-3 border border-gray-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-orange-500 focus:border-transparent transition-all text-gray-900 placeholder-gray-500" - placeholder="Enter your email" - /> -
- -
- -
- setPassword(e.target.value)} - className="w-full px-4 py-3 pr-12 border border-gray-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-orange-500 focus:border-transparent transition-all text-gray-900 placeholder-gray-500" - placeholder="Enter your password" - /> - -
-
-
- -
-
- - -
- - Forgot password? - -
- - - -
-
-
-
-
- Or continue with -
-
- -
- - - -
- - -
-

- Don't have an account?{' '} - - Sign up for free - -

-
-
- - {/* Demo Credentials */} -
-

Demo Credentials

-

- Email: demo@example.com
- Password: password123 -

-
-
-
- ); -} \ No newline at end of file diff --git a/frontend/src/app/marketplace/page.tsx b/frontend/src/app/marketplace/page.tsx deleted file mode 100644 index bf6ce38..0000000 --- a/frontend/src/app/marketplace/page.tsx +++ /dev/null @@ -1,442 +0,0 @@ -'use client'; - -import { useState, useEffect } from 'react'; -import { useAuth } from '@/hooks/useAuth'; -import api from '@/lib/api'; -import { - MagnifyingGlassIcon, - SparklesIcon, - TagIcon, - UserIcon, - ClockIcon, - ArrowDownIcon, - CheckCircleIcon, - ShieldCheckIcon, - CogIcon, - BoltIcon, - CloudIcon, - LockClosedIcon, -} from '@heroicons/react/24/outline'; - -interface Template { - id: string | number; - name: string; - description: string; - category: string; - trigger_type?: string; - tags: string[]; - is_featured?: boolean; - install_count?: number; - useCount?: number; - rating?: number; - author?: string; - icon?: string; - gradient?: string; - complexity?: string; - estimatedTime?: string; - created_at?: string; - createdAt?: string; - source?: 'local' | 'n8n'; - n8n_workflow_id?: string; - n8n_data?: any; - workflow?: any; -} - -export default function MarketplacePage() { - const { user } = useAuth(); - const [templates, setTemplates] = useState([]); - const [filteredTemplates, setFilteredTemplates] = useState([]); - const [loading, setLoading] = useState(true); - const [searchTerm, setSearchTerm] = useState(''); - const [selectedCategory, setSelectedCategory] = useState('all'); - const [installing, setInstalling] = useState(null); - - const categories = [ - { value: 'all', label: 'All Categories', icon: SparklesIcon }, - { value: 'Social Media', label: 'Social Media', icon: UserIcon }, - { value: 'Productivity', label: 'Productivity', icon: ClockIcon }, - { value: 'Communication', label: 'Communication', icon: BoltIcon }, - { value: 'n8n', label: 'N8n Workflows', icon: CloudIcon }, - ]; - - useEffect(() => { - fetchTemplates(); - }, []); - - useEffect(() => { - filterTemplates(); - }, [templates, searchTerm, selectedCategory]); - - const fetchTemplates = async () => { - try { - setLoading(true); - const response = await api.get('/templates'); - setTemplates(response.data.templates || []); - } catch (error) { - console.error('Error fetching templates:', error); - } finally { - setLoading(false); - } - }; - - const filterTemplates = () => { - let filtered = templates; - - if (searchTerm) { - filtered = filtered.filter(template => - template.name.toLowerCase().includes(searchTerm.toLowerCase()) || - template.description.toLowerCase().includes(searchTerm.toLowerCase()) || - template.tags?.some(tag => tag.toLowerCase().includes(searchTerm.toLowerCase())) - ); - } - - if (selectedCategory !== 'all') { - filtered = filtered.filter(template => template.category === selectedCategory); - } - - setFilteredTemplates(filtered); - }; - - const installTemplate = async (templateId: string, templateName: string) => { - try { - setInstalling(templateId); - const response = await api.post(`/templates/${templateId}/install`, { - workflow_name: templateName - }); - - if (response.data.success) { - alert(`${templateName} installed successfully!`); - } - } catch (error: any) { - console.error('Error installing template:', error); - if (error.response?.status === 403) { - alert('Workflow limit reached. Please upgrade your plan to install more templates.'); - } else { - alert('Failed to install template. Please try again.'); - } - } finally { - setInstalling(null); - } - }; - - const getSourceIcon = (template: Template) => { - if (template.source === 'n8n') { - return ; - } - return ; - }; - - const getSourceBadge = (template: Template) => { - if (template.source === 'n8n') { - return ( - - - N8n - - ); - } - return ( - - - Local - - ); - }; - - const canAccessTemplate = (template: Template) => { - // N8n templates are only available to admin users - if (template.source === 'n8n') { - return user?.role === 'admin'; - } - return true; - }; - - const formatDate = (dateString: string) => { - return new Date(dateString).toLocaleDateString('en-US', { - month: 'short', - day: 'numeric', - year: 'numeric' - }); - }; - - if (loading) { - return ( -
-
-
- ); - } - - return ( -
-
- {/* Header */} -
-

Template Marketplace

-

- Discover and install automation templates to jumpstart your workflows -

-
- - {/* Search and Filters */} -
-
- {/* Search */} -
-
- - setSearchTerm(e.target.value)} - className="w-full pl-10 pr-4 py-3 border border-gray-200 rounded-xl focus:ring-2 focus:ring-orange-500 focus:border-transparent" - /> -
-
- - {/* Category Filter */} -
- -
-
- - {/* Stats */} -
-

- Showing {filteredTemplates.length} of {templates.length} templates -

- {user?.role === 'admin' && ( -
- - Admin: N8n templates available -
- )} -
-
- - {/* Templates Grid */} -
- {filteredTemplates.map((template) => { - const hasAccess = canAccessTemplate(template); - - return ( -
- {/* Header */} -
-
-
-
- {template.icon || getSourceIcon(template)} -
-
-

{template.name}

-
- {getSourceBadge(template)} - {template.is_featured && ( - - - Featured - - )} -
-
-
- - {!hasAccess && ( - - )} -
- -

- {template.description} -

- - {/* Rating and Stats */} -
- {template.rating && ( -
-
- {[...Array(5)].map((_, i) => ( - - - - ))} -
- - {template.rating.toFixed(1)} - -
- )} - {template.complexity && ( - - {template.complexity} - - )} - {template.estimatedTime && ( - - - {template.estimatedTime} - - )} -
- - {/* Tags */} - {template.tags && template.tags.length > 0 && ( -
- {template.tags.slice(0, 3).map((tag) => ( - - - {tag} - - ))} - {template.tags.length > 3 && ( - - +{template.tags.length - 3} more - - )} -
- )} -
- - {/* Footer */} -
-
-
- - - {template.useCount || template.install_count || 0} uses - - {(template.created_at || template.createdAt) && ( - - - {formatDate(template.created_at || template.createdAt!)} - - )} - {template.author && ( - - - {template.author} - - )} -
-
- - {hasAccess ? ( - - ) : ( -
-
- - Admin Access Required -
-
- )} -
-
- ); - })} -
- - {/* Empty State */} - {filteredTemplates.length === 0 && ( -
-
- -
-

No templates found

-

- {searchTerm || selectedCategory !== 'all' - ? 'Try adjusting your search or filter criteria.' - : 'There are no templates available at the moment.'} -

- {(searchTerm || selectedCategory !== 'all') && ( - - )} -
- )} - - {/* Info Card */} -
-
-
- -
-
-

About Templates

-

- Templates are pre-built automation workflows that you can install and customize for your needs. - They include pre-configured triggers, actions, and integrations to help you get started quickly. -

- {user?.role === 'admin' && ( -

- Admin Access: You can access N8n workflows directly from your connected N8n instance. - These appear as templates and can be connected to your automation platform. -

- )} -
-
-
-
-
- ); -} \ No newline at end of file diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx deleted file mode 100644 index 553ee10..0000000 --- a/frontend/src/app/page.tsx +++ /dev/null @@ -1,250 +0,0 @@ -'use client'; - -import { useEffect, useState } from 'react'; -import { useRouter } from 'next/navigation'; -import { useAuth } from '@/hooks/useAuth'; -import Link from 'next/link'; -import { - ArrowRightIcon, - SparklesIcon, - BoltIcon, - ShieldCheckIcon, - CpuChipIcon, - PlayIcon, - CheckIcon, -} from '@heroicons/react/24/outline'; - -export default function Home() { - const { user, loading } = useAuth(); - const router = useRouter(); - const [mounted, setMounted] = useState(false); - - useEffect(() => { - setMounted(true); - if (!loading && user) { - router.push('/dashboard'); - } - }, [user, loading, router]); - - if (loading) { - return ( -
-
-
- ); - } - - if (!mounted) return null; - - return ( -
- {/* Navigation */} - - - {/* Hero Section */} -
-
-

- Automate Everything -
- Without Code -

-

- Connect your apps, automate workflows, and boost productivity with our - visual automation platform. No coding required. -

-
- - Start Building Free - - - - - Watch Demo - -
- - {/* Floating Cards */} -
-
- -

Visual Builder

-

Drag and drop to create powerful automations

-
-
- -

Lightning Fast

-

Execute workflows in seconds, not hours

-
-
- -

Secure & Reliable

-

Enterprise-grade security and uptime

-
-
-
-
- - {/* Features Section */} -
-
-
-

- Everything you need to automate -

-

- From simple tasks to complex workflows, our platform scales with your needs -

-
- -
- {[ - { - icon: CpuChipIcon, - title: '500+ Integrations', - description: 'Connect with all your favorite apps and services', - color: 'text-blue-500', - }, - { - icon: BoltIcon, - title: 'Real-time Triggers', - description: 'Instant responses to events across your stack', - color: 'text-orange-500', - }, - { - icon: SparklesIcon, - title: 'AI-Powered', - description: 'Smart suggestions and automated optimizations', - color: 'text-purple-500', - }, - { - icon: ShieldCheckIcon, - title: 'Enterprise Security', - description: 'SOC 2 compliant with end-to-end encryption', - color: 'text-green-500', - }, - { - icon: PlayIcon, - title: 'One-Click Deploy', - description: 'Deploy automations instantly with zero downtime', - color: 'text-red-500', - }, - { - icon: CheckIcon, - title: '99.9% Uptime', - description: 'Reliable execution you can count on', - color: 'text-teal-500', - }, - ].map((feature, index) => ( -
- -

{feature.title}

-

{feature.description}

-
- ))} -
-
-
- - {/* CTA Section */} -
-
-

- Ready to transform your workflow? -

-

- Join thousands of teams already automating their processes -

- - Start Your Free Trial - - -
-
- - {/* Footer */} -
-
-
-
-
-
- -
- Aimpress AutomationHub -
-

- The visual automation platform for modern teams. -

-
-
-

Product

-
    -
  • Features
  • -
  • Integrations
  • -
  • Templates
  • -
  • Pricing
  • -
-
-
-

Support

-
    -
  • Documentation
  • -
  • Help Center
  • -
  • Community
  • -
  • Contact
  • -
-
-
-

Company

-
    -
  • About
  • -
  • Blog
  • -
  • Careers
  • -
  • Privacy
  • -
-
-
-
-

© 2025 Aimpress LTD. All rights reserved.

-
-
-
-
- ); -} diff --git a/frontend/src/app/signup/page.tsx b/frontend/src/app/signup/page.tsx deleted file mode 100644 index 512a1fa..0000000 --- a/frontend/src/app/signup/page.tsx +++ /dev/null @@ -1,109 +0,0 @@ -'use client'; - -import { useState } from 'react'; -import { useAuth } from '@/hooks/useAuth'; -import Link from 'next/link'; -import { useRouter } from 'next/navigation'; - -export default function SignupPage() { - const [email, setEmail] = useState(''); - const [password, setPassword] = useState(''); - const [firstName, setFirstName] = useState(''); - const [lastName, setLastName] = useState(''); - const [loading, setLoading] = useState(false); - const [error, setError] = useState(''); - const { signup } = useAuth(); - const router = useRouter(); - - const handleSubmit = async (e: React.FormEvent) => { - e.preventDefault(); - setLoading(true); - setError(''); - - try { - await signup(email, password, firstName, lastName); - router.push('/dashboard'); - } catch (err: any) { - setError(err.message); - } finally { - setLoading(false); - } - }; - - return ( -
-
-
-

- Create your account -

-

- Or{' '} - - sign in to your existing account - -

-
-
- {error && ( -
- {error} -
- )} -
-
-
- setFirstName(e.target.value)} - className="block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-md focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm" - placeholder="First name" - /> -
-
- setLastName(e.target.value)} - className="block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-md focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm" - placeholder="Last name" - /> -
-
-
- setEmail(e.target.value)} - className="block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-md focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm" - placeholder="Email address" - /> -
-
- setPassword(e.target.value)} - className="block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-md focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm" - placeholder="Password" - /> -
-
- -
- -
-
-
-
- ); -} \ No newline at end of file diff --git a/frontend/src/app/workflows/page.tsx b/frontend/src/app/workflows/page.tsx deleted file mode 100644 index 3ace9da..0000000 --- a/frontend/src/app/workflows/page.tsx +++ /dev/null @@ -1,396 +0,0 @@ -'use client'; - -import { useState, useEffect } from 'react'; -import { useAuth } from '@/hooks/useAuth'; -import api from '@/lib/api'; -import Link from 'next/link'; -import { - PlusIcon, - PlayIcon, - PauseIcon, - CheckCircleIcon, - XCircleIcon, - ClockIcon, - SparklesIcon, - BoltIcon, - ChartBarIcon, - CogIcon, - ArrowTrendingUpIcon, - EyeIcon, - PencilIcon, - TrashIcon, - ArrowPathIcon, -} from '@heroicons/react/24/outline'; - -interface Workflow { - id: string; - name: string; - description: string; - status: string; - trigger_type: string; - is_active: boolean; - n8n_workflow_id?: string; - n8n_data?: any; - created_at: string; - updated_at: string; -} - -interface Execution { - id: string; - finished: boolean; - mode: string; - startedAt: string; - stoppedAt?: string; -} - -export default function WorkflowsPage() { - const { user } = useAuth(); - const [workflows, setWorkflows] = useState([]); - const [loading, setLoading] = useState(true); - const [selectedWorkflow, setSelectedWorkflow] = useState(null); - const [executions, setExecutions] = useState([]); - const [executionsLoading, setExecutionsLoading] = useState(false); - - useEffect(() => { - fetchWorkflows(); - }, []); - - const fetchWorkflows = async () => { - try { - setLoading(true); - const response = await api.get('/workflows'); - setWorkflows(response.data.workflows || []); - } catch (error) { - console.error('Error fetching workflows:', error); - } finally { - setLoading(false); - } - }; - - const fetchExecutions = async (workflowId: string) => { - try { - setExecutionsLoading(true); - const response = await api.get(`/workflows/${workflowId}/executions`); - setExecutions(response.data.executions || []); - } catch (error) { - console.error('Error fetching executions:', error); - } finally { - setExecutionsLoading(false); - } - }; - - const activateWorkflow = async (workflowId: string) => { - try { - await api.post(`/workflows/${workflowId}/activate`); - fetchWorkflows(); // Refresh workflows - } catch (error) { - console.error('Error activating workflow:', error); - } - }; - - const deactivateWorkflow = async (workflowId: string) => { - try { - await api.post(`/workflows/${workflowId}/deactivate`); - fetchWorkflows(); // Refresh workflows - } catch (error) { - console.error('Error deactivating workflow:', error); - } - }; - - const executeWorkflow = async (workflowId: string) => { - try { - await api.post(`/workflows/${workflowId}/execute`); - // Refresh executions if this workflow is selected - if (selectedWorkflow === workflowId) { - fetchExecutions(workflowId); - } - } catch (error) { - console.error('Error executing workflow:', error); - } - }; - - const deleteWorkflow = async (workflowId: string) => { - if (!confirm('Are you sure you want to delete this workflow?')) return; - - try { - await api.delete(`/workflows/${workflowId}`); - fetchWorkflows(); // Refresh workflows - if (selectedWorkflow === workflowId) { - setSelectedWorkflow(null); - setExecutions([]); - } - } catch (error) { - console.error('Error deleting workflow:', error); - } - }; - - const getStatusIcon = (workflow: Workflow) => { - if (workflow.n8n_data?.active || workflow.is_active) { - return ; - } - return ; - }; - - const getStatusColor = (workflow: Workflow) => { - if (workflow.n8n_data?.active || workflow.is_active) { - return 'text-green-700 bg-green-100 border-green-200'; - } - return 'text-gray-700 bg-gray-100 border-gray-200'; - }; - - const formatDate = (dateString: string) => { - return new Date(dateString).toLocaleDateString('en-US', { - month: 'short', - day: 'numeric', - hour: '2-digit', - minute: '2-digit' - }); - }; - - if (loading) { - return ( -
-
-
- ); - } - - return ( -
-
- {/* Header */} -
-
-
-

- Workflows -

-

- Manage your automation workflows connected to n8n -

-
-
- - - - Create Workflow - - -
-
-
- -
- {/* Workflows List */} -
-
-
-

- Your Workflows ({workflows.length}) -

-
- -
- {workflows.length === 0 ? ( -
-
- -
-

No workflows yet

-

- Get started by creating your first automation workflow connected to n8n. -

- - - Create Your First Workflow - -
- ) : ( -
- {workflows.map((workflow) => ( -
{ - setSelectedWorkflow(workflow.id); - fetchExecutions(workflow.id); - }} - > -
-
-
- {getStatusIcon(workflow)} -
-
-

- {workflow.name} -

-

- {workflow.description} -

- {workflow.n8n_workflow_id && ( -

- Connected to n8n: {workflow.n8n_workflow_id} -

- )} -
-
- - {workflow.n8n_data?.active || workflow.is_active ? 'Active' : 'Inactive'} - -
- -
-
- - {workflow.trigger_type || 'Manual'} - - Updated: {formatDate(workflow.updated_at)} -
-
- - {workflow.n8n_data?.active || workflow.is_active ? ( - - ) : ( - - )} - e.stopPropagation()} - > - - - -
-
-
- ))} -
- )} -
-
-
- - {/* Executions Panel */} -
-
-
-

- {selectedWorkflow ? 'Recent Executions' : 'Select Workflow'} -

-
- -
- {!selectedWorkflow ? ( -
- -

- Select a workflow to view its execution history -

-
- ) : executionsLoading ? ( -
-
-
- ) : executions.length === 0 ? ( -
- -

- No executions found for this workflow -

-
- ) : ( -
- {executions.map((execution) => ( -
-
-
- {execution.finished ? ( - - ) : ( - - )} - - {execution.finished ? 'Completed' : 'Running'} - -
- - {formatDate(execution.startedAt)} - -
-
- Mode: {execution.mode} - {execution.stoppedAt && ( - - • Duration: {Math.round((new Date(execution.stoppedAt).getTime() - new Date(execution.startedAt).getTime()) / 1000)}s - - )} -
-
- ))} -
- )} -
-
-
-
-
-
- ); -} \ No newline at end of file diff --git a/frontend/src/components/ClientProvider.tsx b/frontend/src/components/ClientProvider.tsx deleted file mode 100644 index f89bc75..0000000 --- a/frontend/src/components/ClientProvider.tsx +++ /dev/null @@ -1,7 +0,0 @@ -'use client'; - -import { AuthProvider } from '@/hooks/useAuth'; - -export default function ClientProvider({ children }: { children: React.ReactNode }) { - return {children}; -} diff --git a/frontend/src/components/Layout.tsx b/frontend/src/components/Layout.tsx deleted file mode 100644 index ec0385e..0000000 --- a/frontend/src/components/Layout.tsx +++ /dev/null @@ -1,176 +0,0 @@ -'use client'; - -import { useAuth } from '@/hooks/useAuth'; -import Link from 'next/link'; -import { usePathname } from 'next/navigation'; -import { - HomeIcon, - CogIcon, - Squares2X2Icon, - LinkIcon, - DocumentIcon, - ChatBubbleLeftIcon, - ArrowRightOnRectangleIcon, - BoltIcon, - ChartBarIcon, - SparklesIcon, - UserCircleIcon, - ShieldCheckIcon, - CreditCardIcon, -} from '@heroicons/react/24/outline'; - -interface LayoutProps { - children: React.ReactNode; -} - -const navigation = [ - { name: 'Dashboard', href: '/dashboard', icon: HomeIcon, badge: null }, - { name: 'Workflows', href: '/workflows', icon: CogIcon, badge: null }, - { name: 'Templates', href: '/marketplace', icon: Squares2X2Icon, badge: 'New' }, - { name: 'Integrations', href: '/integrations', icon: LinkIcon, badge: null }, - { name: 'Billing', href: '/billing', icon: CreditCardIcon, badge: null }, - { name: 'Logs', href: '/logs', icon: ChartBarIcon, badge: null }, - { name: 'AI Assistant', href: '/chat', icon: SparklesIcon, badge: 'Beta' }, -]; - -export default function Layout({ children }: LayoutProps) { - const { user, logout } = useAuth(); - const pathname = usePathname(); - - // Admin navigation items - const adminNavigation = user?.role === 'admin' ? [ - { name: 'Admin Panel', href: '/admin', icon: ShieldCheckIcon, badge: 'Admin' } - ] : []; - - // Don't show sidebar on auth pages and landing page - if (!user || pathname === '/' || pathname === '/login' || pathname === '/signup') { - return
{children}
; - } - - return ( -
- {/* Sidebar */} -
- {/* Logo */} -
-
-
- -
-
-

Aimpress

-

AutomationHub

-
-
-
- - {/* Navigation */} - - - {/* User Profile */} -
-
-
-
- - {user.first_name?.[0] || user.email[0].toUpperCase()} - -
-
-
-
-

- {user.first_name} {user.last_name} -

-

{user.email}

-

- {user.subscription_plan} Plan -

-
- -
-
-
- - {/* Main content */} -
-
- {children} -
-
- - {/* Floating Action Button */} -
- - - -
-
- ); -} \ No newline at end of file diff --git a/frontend/src/hooks/useAuth.tsx b/frontend/src/hooks/useAuth.tsx deleted file mode 100644 index de9c873..0000000 --- a/frontend/src/hooks/useAuth.tsx +++ /dev/null @@ -1,87 +0,0 @@ -"use client"; - -import { useState, useEffect, createContext, useContext } from "react"; -import { User } from "@/types"; -import api from "@/lib/api"; - -interface AuthContextType { - user: User | null; - token: string | null; - login: (email: string, password: string) => Promise; - signup: (email: string, password: string, firstName?: string, lastName?: string) => Promise; - logout: () => void; - loading: boolean; -} - -const AuthContext = createContext(undefined); - -export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { - const [user, setUser] = useState(null); - const [token, setToken] = useState(null); - const [loading, setLoading] = useState(true); - - useEffect(() => { - const savedToken = localStorage.getItem("token"); - const savedUser = localStorage.getItem("user"); - - if (savedToken && savedUser) { - setToken(savedToken); - setUser(JSON.parse(savedUser)); - } - setLoading(false); - }, []); - - const login = async (email: string, password: string) => { - try { - const response = await api.post("/auth/login", { email, password }); - const { token, user } = response.data; - - localStorage.setItem("token", token); - localStorage.setItem("user", JSON.stringify(user)); - setToken(token); - setUser(user); - } catch (error: any) { - throw new Error(error.response?.data?.message || "Login failed"); - } - }; - - const signup = async (email: string, password: string, firstName?: string, lastName?: string) => { - try { - const response = await api.post("/auth/signup", { - email, - password, - first_name: firstName, - last_name: lastName, - }); - const { token, user } = response.data; - - localStorage.setItem("token", token); - localStorage.setItem("user", JSON.stringify(user)); - setToken(token); - setUser(user); - } catch (error: any) { - throw new Error(error.response?.data?.message || "Signup failed"); - } - }; - - const logout = () => { - localStorage.removeItem("token"); - localStorage.removeItem("user"); - setToken(null); - setUser(null); - }; - - return ( - - {children} - - ); -}; - -export const useAuth = () => { - const context = useContext(AuthContext); - if (context === undefined) { - throw new Error("useAuth must be used within an AuthProvider"); - } - return context; -}; diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts deleted file mode 100644 index ad817a1..0000000 --- a/frontend/src/lib/api.ts +++ /dev/null @@ -1,32 +0,0 @@ -import axios from 'axios'; - -const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001'; - -const api = axios.create({ - baseURL: API_BASE_URL, - headers: { - 'Content-Type': 'application/json', - }, -}); - -api.interceptors.request.use((config) => { - const token = localStorage.getItem('token'); - if (token) { - config.headers.Authorization = `Bearer ${token}`; - } - return config; -}); - -api.interceptors.response.use( - (response) => response, - (error) => { - if (error.response?.status === 401) { - localStorage.removeItem('token'); - localStorage.removeItem('user'); - window.location.href = '/login'; - } - return Promise.reject(error); - } -); - -export default api; \ No newline at end of file diff --git a/frontend/src/types/index.ts b/frontend/src/types/index.ts deleted file mode 100644 index 44b6834..0000000 --- a/frontend/src/types/index.ts +++ /dev/null @@ -1,75 +0,0 @@ -export interface User { - id: number; - email: string; - first_name?: string; - last_name?: string; - is_verified: boolean; - role: string; - subscription_plan: string; - subscription_status: string; - created_at: string; - updated_at: string; -} - -export interface Workflow { - id: number; - name: string; - description?: string; - status: string; - trigger_type: string; - is_active: boolean; - created_at: string; - updated_at: string; -} - -export interface Template { - id: number; - name: string; - description?: string; - category: string; - trigger_type: string; - tags: string[]; - is_featured: boolean; - install_count: number; - created_at: string; -} - -export interface Integration { - id: number; - provider: string; - account_name?: string; - account_email?: string; - is_active: boolean; - created_at: string; - updated_at: string; -} - -export interface Webhook { - id: number; - name: string; - slug: string; - trigger_type: string; - url_path: string; - is_active: boolean; - secret_key?: string; - created_at: string; - updated_at: string; -} - -export interface WorkflowExecution { - id: number; - workflow_id: number; - workflow_name: string; - status: string; - trigger_data: any; - error_message?: string; - started_at?: string; - finished_at?: string; - created_at: string; -} - -export interface ChatMessage { - message_type: 'user' | 'assistant'; - content: string; - created_at: string; -} \ No newline at end of file diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json deleted file mode 100644 index c133409..0000000 --- a/frontend/tsconfig.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2017", - "lib": ["dom", "dom.iterable", "esnext"], - "allowJs": true, - "skipLibCheck": true, - "strict": true, - "noEmit": true, - "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "bundler", - "resolveJsonModule": true, - "isolatedModules": true, - "jsx": "preserve", - "incremental": true, - "plugins": [ - { - "name": "next" - } - ], - "paths": { - "@/*": ["./src/*"] - } - }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], - "exclude": ["node_modules"] -} diff --git a/server-new.js b/server-new.js deleted file mode 100644 index ea838cc..0000000 --- a/server-new.js +++ /dev/null @@ -1,334 +0,0 @@ -const express = require('express'); -const path = require('path'); -const session = require('express-session'); -const bcrypt = require('bcrypt'); -const helmet = require('helmet'); -const cors = require('cors'); -require('dotenv').config(); - -// Инициализация базы данных -const { db, initDatabase } = require('./database/init'); - -const app = express(); -const port = process.env.PORT || 3000; - -// Middleware -app.use(helmet({ - contentSecurityPolicy: false, // Отключаем для удобства разработки -})); -app.use(cors()); -app.use(express.json()); -app.use(express.urlencoded({ extended: true })); -app.use(express.static(path.join(__dirname, 'public'))); - -// Сессии -app.use(session({ - secret: process.env.SESSION_SECRET || 'your-secret-key-change-in-production', - resave: false, - saveUninitialized: false, - cookie: { - secure: process.env.NODE_ENV === 'production', - maxAge: 24 * 60 * 60 * 1000 // 24 часа - } -})); - -// Middleware для проверки аутентификации -function requireAuth(req, res, next) { - if (req.session.userId) { - next(); - } else { - res.status(401).json({ error: 'Authentication required' }); - } -} - -// Основная страница - старая функциональность счетчика кликов -app.get('/', (req, res) => { - res.sendFile(path.join(__dirname, 'public', 'index.html')); -}); - -// Health check -app.get('/health', (req, res) => { - res.json({ status: 'ok', timestamp: new Date().toISOString() }); -}); - -// API Routes -app.post('/api/auth/login', (req, res) => { - const { email, password } = req.body; - - if (!email || !password) { - return res.status(400).json({ error: 'Email and password are required' }); - } - - db.get('SELECT * FROM users WHERE email = ?', [email], (err, user) => { - if (err) { - return res.status(500).json({ error: 'Database error' }); - } - - if (!user) { - return res.status(401).json({ error: 'Invalid credentials' }); - } - - bcrypt.compare(password, user.password_hash, (err, isValid) => { - if (err || !isValid) { - return res.status(401).json({ error: 'Invalid credentials' }); - } - - req.session.userId = user.id; - req.session.username = user.username; - - res.json({ - user: { - id: user.id, - username: user.username, - email: user.email, - subscription_type: user.subscription_type - } - }); - }); - }); -}); - -app.post('/api/auth/register', (req, res) => { - const { username, email, password } = req.body; - - if (!username || !email || !password) { - return res.status(400).json({ error: 'Username, email and password are required' }); - } - - if (password.length < 6) { - return res.status(400).json({ error: 'Password must be at least 6 characters' }); - } - - bcrypt.hash(password, 10, (err, hash) => { - if (err) { - return res.status(500).json({ error: 'Error hashing password' }); - } - - db.run('INSERT INTO users (username, email, password_hash) VALUES (?, ?, ?)', - [username, email, hash], function(err) { - if (err) { - if (err.code === 'SQLITE_CONSTRAINT') { - return res.status(400).json({ error: 'Username or email already exists' }); - } - return res.status(500).json({ error: 'Database error' }); - } - - req.session.userId = this.lastID; - req.session.username = username; - - res.status(201).json({ - user: { - id: this.lastID, - username, - email, - subscription_type: 'free' - } - }); - }); - }); -}); - -app.post('/api/auth/logout', (req, res) => { - req.session.destroy((err) => { - if (err) { - return res.status(500).json({ error: 'Error logging out' }); - } - res.json({ message: 'Logged out successfully' }); - }); -}); - -// Получение информации о пользователе -app.get('/api/user/profile', requireAuth, (req, res) => { - db.get('SELECT id, username, email, subscription_type, created_at FROM users WHERE id = ?', - [req.session.userId], (err, user) => { - if (err) { - return res.status(500).json({ error: 'Database error' }); - } - res.json({ user }); - }); -}); - -// Управление credentials -app.get('/api/user/credentials', requireAuth, (req, res) => { - db.all(`SELECT id, service_name, credential_type, description, created_at - FROM user_credentials WHERE user_id = ? AND is_active = 1`, - [req.session.userId], (err, credentials) => { - if (err) { - return res.status(500).json({ error: 'Database error' }); - } - res.json({ credentials }); - }); -}); - -app.post('/api/user/credentials', requireAuth, (req, res) => { - const { service_name, credential_type, value, description } = req.body; - - if (!service_name || !credential_type || !value) { - return res.status(400).json({ error: 'Missing required fields' }); - } - - // Простое "шифрование" - в продакшене используйте настоящее шифрование - const encrypted_value = Buffer.from(value).toString('base64'); - - db.run(`INSERT OR REPLACE INTO user_credentials - (user_id, service_name, credential_type, encrypted_value, description) - VALUES (?, ?, ?, ?, ?)`, - [req.session.userId, service_name, credential_type, encrypted_value, description], - function(err) { - if (err) { - return res.status(500).json({ error: 'Database error' }); - } - res.status(201).json({ - id: this.lastID, - message: 'Credential saved successfully' - }); - }); -}); - -app.delete('/api/user/credentials/:id', requireAuth, (req, res) => { - const credentialId = req.params.id; - - db.run('DELETE FROM user_credentials WHERE id = ? AND user_id = ?', - [credentialId, req.session.userId], function(err) { - if (err) { - return res.status(500).json({ error: 'Database error' }); - } - if (this.changes === 0) { - return res.status(404).json({ error: 'Credential not found' }); - } - res.json({ message: 'Credential deleted successfully' }); - }); -}); - -// Шаблоны рабочих процессов -app.get('/api/templates', (req, res) => { - const { category, featured } = req.query; - let query = 'SELECT * FROM workflow_templates WHERE is_active = 1'; - const params = []; - - if (category) { - query += ' AND category = ?'; - params.push(category); - } - - if (featured === 'true') { - query += ' AND is_featured = 1'; - } - - query += ' ORDER BY is_featured DESC, created_at DESC'; - - db.all(query, params, (err, templates) => { - if (err) { - return res.status(500).json({ error: 'Database error' }); - } - - // Парсим JSON поля - const processedTemplates = templates.map(template => ({ - ...template, - template_data: JSON.parse(template.template_data), - required_credentials: JSON.parse(template.required_credentials) - })); - - res.json({ templates: processedTemplates }); - }); -}); - -app.get('/api/templates/:id', (req, res) => { - const templateId = req.params.id; - - db.get('SELECT * FROM workflow_templates WHERE id = ? AND is_active = 1', - [templateId], (err, template) => { - if (err) { - return res.status(500).json({ error: 'Database error' }); - } - if (!template) { - return res.status(404).json({ error: 'Template not found' }); - } - - // Парсим JSON поля - template.template_data = JSON.parse(template.template_data); - template.required_credentials = JSON.parse(template.required_credentials); - - res.json({ template }); - }); -}); - -// Пользовательские рабочие процессы -app.get('/api/user/workflows', requireAuth, (req, res) => { - db.all(`SELECT uw.*, wt.name as template_name - FROM user_workflows uw - LEFT JOIN workflow_templates wt ON uw.template_id = wt.id - WHERE uw.user_id = ? - ORDER BY uw.created_at DESC`, - [req.session.userId], (err, workflows) => { - if (err) { - return res.status(500).json({ error: 'Database error' }); - } - res.json({ workflows }); - }); -}); - -app.post('/api/user/workflows', requireAuth, (req, res) => { - const { template_id, workflow_name, configuration } = req.body; - - if (!workflow_name) { - return res.status(400).json({ error: 'Workflow name is required' }); - } - - db.run(`INSERT INTO user_workflows (user_id, template_id, workflow_name, configuration) - VALUES (?, ?, ?, ?)`, - [req.session.userId, template_id || null, workflow_name, JSON.stringify(configuration || {})], - function(err) { - if (err) { - return res.status(500).json({ error: 'Database error' }); - } - res.status(201).json({ - id: this.lastID, - message: 'Workflow created successfully' - }); - }); -}); - -// Статистика использования -app.get('/api/user/stats', requireAuth, (req, res) => { - const queries = [ - 'SELECT COUNT(*) as total_workflows FROM user_workflows WHERE user_id = ?', - 'SELECT COUNT(*) as total_credentials FROM user_credentials WHERE user_id = ? AND is_active = 1', - 'SELECT COUNT(*) as total_executions FROM usage_stats WHERE user_id = ?' - ]; - - Promise.all(queries.map(query => new Promise((resolve, reject) => { - db.get(query, [req.session.userId], (err, result) => { - if (err) reject(err); - else resolve(result); - }); - }))).then(results => { - res.json({ - stats: { - total_workflows: results[0].total_workflows, - total_credentials: results[1].total_credentials, - total_executions: results[2].total_executions - } - }); - }).catch(() => { - res.status(500).json({ error: 'Database error' }); - }); -}); - -// Инициализация приложения -async function startApp() { - try { - await initDatabase(); - - app.listen(port, () => { - console.log(`🚀 SaaS Automation Platform running on http://localhost:${port}`); - console.log(`📊 Health check available at: http://localhost:${port}/health`); - console.log(`🔑 Demo credentials: demo@example.com / demo123`); - }); - } catch (error) { - console.error('❌ Failed to initialize application:', error); - process.exit(1); - } -} - -startApp(); \ No newline at end of file diff --git a/server-old.js b/server-old.js deleted file mode 100644 index 7488a74..0000000 --- a/server-old.js +++ /dev/null @@ -1,17 +0,0 @@ -const express = require('express'); -const path = require('path'); - -// __dirname уже доступен в CommonJS - -const app = express(); -const port = process.env.PORT || 3000; - -app.use(express.static(path.join(__dirname, 'public'))); - -app.get('/health', (req, res) => { - res.json({ status: 'ok' }); -}); - -app.listen(port, () => { - console.log(`Server is running on http://localhost:${port}`); -});