diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..a547bf36d --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/API_DOCUMENTATION.md b/API_DOCUMENTATION.md new file mode 100644 index 000000000..40231f487 --- /dev/null +++ b/API_DOCUMENTATION.md @@ -0,0 +1,819 @@ +# ๐ŸŒธ SHE_WANTS - API Documentation + +## Base URL +``` +http://localhost:3000/api +``` + +For production, replace with your deployed backend URL. + +--- + +## ๐Ÿ“‘ Table of Contents +1. [Authentication](#authentication) +2. [Period Tracking](#period-tracking) +3. [Pad Requests](#pad-requests) +4. [Community Helpers](#community-helpers) +5. [Sisterhood Posts](#sisterhood-posts) + +--- + +## ๐Ÿ” Authentication + +### Register User +**POST** `/auth/register` + +**Description:** Create a new user account + +**Request Body:** +```json +{ + "username": "johndoe", + "email": "john@example.com", + "password": "securePassword123", + "secretCode": "1234=" +} +``` + +**Response (Success - 201):** +```json +{ + "message": "User registered successfully!", + "userId": 1 +} +``` + +**Response (Error - 400):** +```json +{ + "error": "Username already exists" +} +``` + +--- + +### Login User +**POST** `/auth/login` + +**Description:** Authenticate user and get user details + +**Request Body:** +```json +{ + "username": "johndoe", + "password": "securePassword123" +} +``` + +**Response (Success - 200):** +```json +{ + "message": "Login successful!", + "user": { + "id": 1, + "username": "johndoe", + "email": "john@example.com", + "secret_code": "1234=" + } +} +``` + +**Response (Error - 401):** +```json +{ + "error": "Invalid credentials" +} +``` + +--- + +## ๐ŸŒธ Period Tracking + +### Get User Cycles +**GET** `/cycles/:userId` + +**Description:** Retrieve all menstrual cycles for a user with statistics + +**Parameters:** +- `userId` (path parameter) - User ID + +**Response (Success - 200):** +```json +{ + "cycles": [ + { + "id": 1, + "user_id": 1, + "start_date": "2024-01-15", + "created_at": "2024-01-15 10:30:00" + }, + { + "id": 2, + "user_id": 1, + "start_date": "2024-02-12", + "created_at": "2024-02-12 09:15:00" + } + ], + "statistics": { + "totalCycles": 2, + "averageCycleLength": 28, + "shortestCycle": 26, + "longestCycle": 30 + } +} +``` + +--- + +### Add Cycle +**POST** `/cycles` + +**Description:** Log a new menstrual cycle start date + +**Request Body:** +```json +{ + "userId": 1, + "startDate": "2024-03-10" +} +``` + +**Response (Success - 201):** +```json +{ + "id": 3, + "message": "Cycle added successfully!" +} +``` + +**Response (Error - 400):** +```json +{ + "error": "Cycle already exists for this date" +} +``` + +--- + +### Delete Cycle +**DELETE** `/cycles/:cycleId` + +**Description:** Delete a specific cycle entry + +**Parameters:** +- `cycleId` (path parameter) - Cycle ID to delete + +**Response (Success - 200):** +```json +{ + "message": "Cycle deleted successfully!" +} +``` + +--- + +## ๐Ÿฉธ Pad Requests + +### Create Pad Request +**POST** `/pad-request` + +**Description:** Create a new emergency pad request with location + +**Request Body:** +```json +{ + "userId": 1, + "username": "johndoe", + "latitude": 10.8242, + "longitude": 76.6424 +} +``` + +**Response (Success - 201):** +```json +{ + "id": 15, + "message": "Pad request created successfully!" +} +``` + +**Response (Error - 400):** +```json +{ + "error": "User ID, username, and location are required" +} +``` + +--- + +### Get Nearby Requests +**GET** `/pad-requests/nearby/:userId` + +**Description:** Get all active pad requests except from the current user + +**Parameters:** +- `userId` (path parameter) - Current user's ID (to exclude their own requests) + +**Response (Success - 200):** +```json +{ + "requests": [ + { + "id": 16, + "user_id": 7, + "username": "riyarose05@gmail.com", + "latitude": 10.824396479440194, + "longitude": 76.64222566641749, + "created_at": "2026-02-14 01:07:46" + }, + { + "id": 15, + "user_id": 7, + "username": "riyarose05@gmail.com", + "latitude": 10.824396479440194, + "longitude": 76.64222566641749, + "created_at": "2026-02-14 01:07:03" + } + ] +} +``` + +--- + +### Get My Requests +**GET** `/pad-requests/my/:userId` + +**Description:** Get all pad requests created by the current user + +**Parameters:** +- `userId` (path parameter) - User ID + +**Response (Success - 200):** +```json +{ + "requests": [ + { + "id": 20, + "user_id": 1, + "username": "johndoe", + "latitude": 10.8242, + "longitude": 76.6424, + "status": "active", + "created_at": "2026-02-14 08:00:00" + } + ] +} +``` + +--- + +### Fulfill Pad Request +**POST** `/pad-request/fulfill` + +**Description:** Mark a pad request as fulfilled + +**Request Body:** +```json +{ + "requestId": 16, + "fulfilledBy": 1 +} +``` + +**Response (Success - 200):** +```json +{ + "message": "Request marked as fulfilled!" +} +``` + +**Response (Error - 500):** +```json +{ + "error": "Database error message" +} +``` + +--- + +## ๐Ÿ’ Community Helpers + +### Register as Helper +**POST** `/helpers/register` + +**Description:** Register as a community helper + +**Request Body:** +```json +{ + "userId": 1, + "username": "johndoe", + "bio": "Happy to help women in need. Available weekdays 9-5.", + "location": "Downtown, City Center" +} +``` + +**Response (Success - 201):** +```json +{ + "message": "Registered as helper successfully!" +} +``` + +**Response (Error - 400):** +```json +{ + "error": "User ID, username, and bio are required" +} +``` + +--- + +### Get All Helpers +**GET** `/helpers` + +**Description:** Get all registered community helpers + +**Response (Success - 200):** +```json +{ + "helpers": [ + { + "id": 1, + "user_id": 5, + "username": "helper1", + "bio": "Happy to help!", + "location": "Downtown", + "created_at": "2026-02-10 10:00:00" + }, + { + "id": 2, + "user_id": 8, + "username": "helper2", + "bio": "Available 24/7", + "location": "North Side", + "created_at": "2026-02-11 14:30:00" + } + ] +} +``` + +--- + +### Check Helper Status +**GET** `/helpers/status/:userId` + +**Description:** Check if a user is registered as a helper + +**Parameters:** +- `userId` (path parameter) - User ID to check + +**Response (Success - 200):** +```json +{ + "isHelper": true, + "helper": { + "id": 1, + "user_id": 5, + "username": "helper1", + "bio": "Happy to help!", + "location": "Downtown" + } +} +``` + +**Response (Not a helper - 200):** +```json +{ + "isHelper": false +} +``` + +--- + +### Remove Helper Status +**DELETE** `/helpers/:userId` + +**Description:** Remove helper status from a user + +**Parameters:** +- `userId` (path parameter) - User ID + +**Response (Success - 200):** +```json +{ + "message": "Helper status removed successfully" +} +``` + +--- + +## ๐Ÿ’ฌ Sisterhood Posts + +### Get All Posts +**GET** `/posts` + +**Description:** Get all posts or filter by category + +**Query Parameters:** +- `category` (optional) - Filter by category (breakup, selfcare, health, relationships, advice, general) + +**Examples:** +- `/posts` - Get all posts +- `/posts?category=breakup` - Get only breakup support posts + +**Response (Success - 200):** +```json +{ + "posts": [ + { + "id": 1, + "user_id": 3, + "username": "Anonymous", + "category": "breakup", + "content": "Going through a tough breakup. Any advice?", + "is_anonymous": 1, + "likes_count": 5, + "comments_count": 3, + "created_at": "2026-02-14 07:30:00" + }, + { + "id": 2, + "user_id": 5, + "username": "jane_doe", + "category": "selfcare", + "content": "Self-care Sunday! What are your favorite routines?", + "is_anonymous": 0, + "likes_count": 12, + "comments_count": 8, + "created_at": "2026-02-14 06:15:00" + } + ] +} +``` + +--- + +### Create Post +**POST** `/posts` + +**Description:** Create a new sisterhood post + +**Request Body:** +```json +{ + "userId": 1, + "username": "johndoe", + "category": "advice", + "content": "Looking for career advice. How do you balance work and personal life?", + "isAnonymous": false +} +``` + +**Response (Success - 201):** +```json +{ + "id": 25, + "message": "Post created successfully" +} +``` + +**Response (Error - 400):** +```json +{ + "error": "Content and category are required" +} +``` + +--- + +### Get Single Post with Comments +**GET** `/posts/:postId` + +**Description:** Get a specific post with all its comments + +**Parameters:** +- `postId` (path parameter) - Post ID + +**Response (Success - 200):** +```json +{ + "post": { + "id": 1, + "user_id": 3, + "username": "Anonymous", + "category": "breakup", + "content": "Going through a tough breakup. Any advice?", + "is_anonymous": 1, + "likes_count": 5, + "comments_count": 3, + "created_at": "2026-02-14 07:30:00" + }, + "comments": [ + { + "id": 1, + "post_id": 1, + "user_id": 5, + "username": "supportive_friend", + "comment": "Stay strong! Time heals everything.", + "is_anonymous": 0, + "created_at": "2026-02-14 08:00:00" + }, + { + "id": 2, + "post_id": 1, + "user_id": 7, + "username": "Anonymous", + "comment": "I went through the same thing. It gets better!", + "is_anonymous": 1, + "created_at": "2026-02-14 08:15:00" + } + ] +} +``` + +**Response (Error - 404):** +```json +{ + "error": "Post not found" +} +``` + +--- + +### Like/Unlike Post +**POST** `/posts/:postId/like` + +**Description:** Toggle like on a post (like if not liked, unlike if already liked) + +**Parameters:** +- `postId` (path parameter) - Post ID + +**Request Body:** +```json +{ + "userId": 1 +} +``` + +**Response (Liked - 200):** +```json +{ + "liked": true, + "message": "Post liked" +} +``` + +**Response (Unliked - 200):** +```json +{ + "liked": false, + "message": "Post unliked" +} +``` + +--- + +### Check Like Status +**GET** `/posts/:postId/liked/:userId` + +**Description:** Check if a user has liked a specific post + +**Parameters:** +- `postId` (path parameter) - Post ID +- `userId` (path parameter) - User ID + +**Response (Success - 200):** +```json +{ + "liked": true +} +``` + +--- + +### Add Comment +**POST** `/posts/:postId/comment` + +**Description:** Add a comment to a post + +**Parameters:** +- `postId` (path parameter) - Post ID + +**Request Body:** +```json +{ + "userId": 1, + "username": "johndoe", + "comment": "Great advice! Thank you for sharing.", + "isAnonymous": false +} +``` + +**Response (Success - 201):** +```json +{ + "id": 15, + "message": "Comment added successfully" +} +``` + +**Response (Error - 400):** +```json +{ + "error": "Comment is required" +} +``` + +--- + +## ๐Ÿ“Š Response Status Codes + +| Code | Meaning | Usage | +|------|---------|-------| +| 200 | OK | Successful GET, PUT, DELETE requests | +| 201 | Created | Successful POST requests that create resources | +| 400 | Bad Request | Invalid request body or parameters | +| 401 | Unauthorized | Invalid credentials | +| 404 | Not Found | Resource not found | +| 500 | Internal Server Error | Database or server errors | + +--- + +## ๐Ÿ”’ Error Response Format + +All errors follow this format: + +```json +{ + "error": "Descriptive error message" +} +``` + +--- + +## ๐Ÿ“ Notes + +### Categories for Posts +Valid categories for sisterhood posts: +- `breakup` - Breakup Support +- `selfcare` - Self-Care +- `health` - Health +- `relationships` - Relationships +- `advice` - Advice +- `general` - General + +### Anonymous Posting +- When `isAnonymous` is `true`, the username is replaced with "Anonymous" in the database +- The actual `user_id` is still stored for moderation purposes + +### Location Data +- Latitude and longitude should be decimal degrees +- Example: `10.8242, 76.6424` +- Obtained from browser's Geolocation API + +### Timestamps +- All timestamps are in format: `YYYY-MM-DD HH:MM:SS` +- Timezone: Server local time (adjust for production) + +--- + +## ๐Ÿงช Testing the API + +### Using cURL + +**Register a user:** +```bash +curl -X POST http://localhost:3000/api/auth/register \ + -H "Content-Type: application/json" \ + -d '{ + "username": "testuser2", + "email": "test2@example.com", + "password": "password123", + "secretCode": "1234=" + }' +``` + +**Login:** +```bash +curl -X POST http://localhost:3000/api/auth/login \ + -H "Content-Type: application/json" \ + -d '{ + "username": "testuser", + "password": "password123" + }' +``` + +**Get nearby requests:** +```bash +curl http://localhost:3000/api/pad-requests/nearby/1 +``` + +**Create a post:** +```bash +curl -X POST http://localhost:3000/api/posts \ + -H "Content-Type: application/json" \ + -d '{ + "userId": 1, + "username": "testuser", + "category": "advice", + "content": "Test post content", + "isAnonymous": false + }' +``` + +### Using JavaScript (Axios) + +```javascript +import axios from 'axios'; + +const api = axios.create({ + baseURL: 'http://localhost:3000/api' +}); + +// Login +const login = async () => { + const response = await api.post('/auth/login', { + username: 'testuser', + password: 'password123' + }); + return response.data; +}; + +// Get cycles +const getCycles = async (userId) => { + const response = await api.get(`/cycles/${userId}`); + return response.data; +}; + +// Create pad request +const createPadRequest = async (userId, username, lat, lng) => { + const response = await api.post('/pad-request', { + userId, + username, + latitude: lat, + longitude: lng + }); + return response.data; +}; +``` + +--- + +## ๐Ÿ” Security Considerations + +1. **Password Hashing**: All passwords are hashed using bcrypt before storage +2. **SQL Injection Prevention**: All queries use parameterized statements +3. **Input Validation**: All endpoints validate required fields +4. **CORS**: Enabled for frontend communication + +### Recommended for Production: +- Add JWT authentication +- Implement rate limiting +- Add request validation middleware +- Use HTTPS only +- Add API key authentication +- Implement proper session management + +--- + +## ๐Ÿ“ˆ Rate Limiting (Recommended) + +For production, implement rate limiting: + +```javascript +const rateLimit = require('express-rate-limit'); + +const limiter = rateLimit({ + windowMs: 15 * 60 * 1000, // 15 minutes + max: 100 // limit each IP to 100 requests per windowMs +}); + +app.use('/api/', limiter); +``` + +--- + +## ๐ŸŽฏ Quick Reference + +| Feature | Endpoint | Method | +|---------|----------|--------| +| Register | `/auth/register` | POST | +| Login | `/auth/login` | POST | +| Get Cycles | `/cycles/:userId` | GET | +| Add Cycle | `/cycles` | POST | +| Create Pad Request | `/pad-request` | POST | +| Get Nearby Requests | `/pad-requests/nearby/:userId` | GET | +| Fulfill Request | `/pad-request/fulfill` | POST | +| Register Helper | `/helpers/register` | POST | +| Get Helpers | `/helpers` | GET | +| Get Posts | `/posts` | GET | +| Create Post | `/posts` | POST | +| Like Post | `/posts/:postId/like` | POST | +| Add Comment | `/posts/:postId/comment` | POST | + +--- + +**API Version:** 1.0 +**Last Updated:** February 14, 2026 +**Base URL:** `http://localhost:3000/api` diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md new file mode 100644 index 000000000..2999fa0e9 --- /dev/null +++ b/DEPLOYMENT.md @@ -0,0 +1,495 @@ +# ๐Ÿš€ SHE_WANTS - Deployment Guide + +## Quick Deployment Options + +### Option 1: Vercel (Frontend) + Render (Backend) - **RECOMMENDED** โœ… +**Best for:** Easy deployment, free tier available, automatic HTTPS + +### Option 2: Netlify (Frontend) + Railway (Backend) +**Best for:** Simple setup, good free tier + +### Option 3: GitHub Pages (Frontend only - Static) +**Best for:** Quick demo, no backend needed + +### Option 4: Heroku (Full Stack) +**Best for:** All-in-one deployment + +--- + +## ๐ŸŒŸ Option 1: Vercel + Render (RECOMMENDED) + +### Part A: Deploy Frontend to Vercel + +#### Step 1: Prepare Your Project +```bash +# Build the frontend +npm run build +``` + +#### Step 2: Deploy to Vercel + +**Method 1: Using Vercel CLI (Fastest)** +```bash +# Install Vercel CLI +npm install -g vercel + +# Login to Vercel +vercel login + +# Deploy +cd /Users/macbookair/Desktop/SHE_WANTS +vercel --prod +``` + +**Method 2: Using Vercel Website** +1. Go to https://vercel.com +2. Sign up/Login with GitHub +3. Click "Add New Project" +4. Import your GitHub repository +5. Configure: + - Framework Preset: Vite + - Build Command: `npm run build` + - Output Directory: `dist` + - Install Command: `npm install` +6. Click "Deploy" + +#### Step 3: Get Your Frontend URL +After deployment, you'll get a URL like: +``` +https://she-wants.vercel.app +``` + +--- + +### Part B: Deploy Backend to Render + +#### Step 1: Create render.yaml +Create a file `render.yaml` in your project root: + +```yaml +services: + - type: web + name: she-wants-backend + env: node + buildCommand: npm install + startCommand: node server/index.js + envVars: + - key: NODE_ENV + value: production + - key: PORT + value: 3000 +``` + +#### Step 2: Update server/index.js for Production +Add this at the top of `server/index.js`: + +```javascript +const PORT = process.env.PORT || 3000; +``` + +And update the CORS configuration: + +```javascript +app.use(cors({ + origin: ['https://she-wants.vercel.app', 'http://localhost:5173'], + credentials: true +})); +``` + +#### Step 3: Deploy to Render + +1. Go to https://render.com +2. Sign up/Login with GitHub +3. Click "New +" โ†’ "Web Service" +4. Connect your GitHub repository +5. Configure: + - Name: `she-wants-backend` + - Environment: `Node` + - Build Command: `npm install` + - Start Command: `node server/index.js` + - Instance Type: Free +6. Add Environment Variables: + - `NODE_ENV` = `production` +7. Click "Create Web Service" + +#### Step 4: Get Your Backend URL +After deployment, you'll get a URL like: +``` +https://she-wants-backend.onrender.com +``` + +#### Step 5: Update Frontend API Configuration + +Update `src/config/api.js`: + +```javascript +import axios from 'axios'; + +const api = axios.create({ + baseURL: import.meta.env.PROD + ? 'https://she-wants-backend.onrender.com/api' + : 'http://localhost:3000/api' +}); + +export default api; +``` + +#### Step 6: Redeploy Frontend +```bash +npm run build +vercel --prod +``` + +--- + +## ๐ŸŽฏ Option 2: Netlify + Railway + +### Deploy Frontend to Netlify + +#### Step 1: Build +```bash +npm run build +``` + +#### Step 2: Deploy + +**Using Netlify CLI:** +```bash +# Install Netlify CLI +npm install -g netlify-cli + +# Login +netlify login + +# Deploy +netlify deploy --prod --dir=dist +``` + +**Using Netlify Website:** +1. Go to https://netlify.com +2. Drag and drop your `dist` folder +3. Or connect GitHub repository + +### Deploy Backend to Railway + +1. Go to https://railway.app +2. Login with GitHub +3. Click "New Project" +4. Select "Deploy from GitHub repo" +5. Choose your repository +6. Railway auto-detects Node.js +7. Add environment variables +8. Deploy + +Your backend URL: `https://she-wants-backend.up.railway.app` + +--- + +## ๐Ÿ“„ Option 3: GitHub Pages (Static Demo) + +**Note:** This only deploys the frontend as a static site. Backend features won't work. + +#### Step 1: Update vite.config.js + +```javascript +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +export default defineConfig({ + plugins: [react()], + base: '/SHE_WANTS/' // Replace with your repo name +}) +``` + +#### Step 2: Build +```bash +npm run build +``` + +#### Step 3: Deploy + +**Using gh-pages:** +```bash +# Install gh-pages +npm install -g gh-pages + +# Deploy +gh-pages -d dist +``` + +**Manual Method:** +1. Go to GitHub repository settings +2. Pages โ†’ Source โ†’ Select branch `gh-pages` +3. Save + +Your site: `https://yourusername.github.io/SHE_WANTS/` + +--- + +## ๐Ÿ”ง Option 4: Heroku (Full Stack) + +#### Step 1: Create Procfile + +Create `Procfile` in project root: +``` +web: npm run server:dev +``` + +#### Step 2: Update package.json + +Add to scripts: +```json +{ + "scripts": { + "start": "node server/index.js", + "heroku-postbuild": "npm run build" + } +} +``` + +#### Step 3: Deploy + +```bash +# Install Heroku CLI +# Download from https://devcenter.heroku.com/articles/heroku-cli + +# Login +heroku login + +# Create app +heroku create she-wants-app + +# Deploy +git push heroku main + +# Open app +heroku open +``` + +Your app: `https://she-wants-app.herokuapp.com` + +--- + +## ๐Ÿ” Environment Variables for Production + +Create `.env.production` file: + +```env +# Backend URL +VITE_API_URL=https://she-wants-backend.onrender.com/api + +# Database +DB_PATH=./server/shewants.db + +# Server +PORT=3000 +NODE_ENV=production + +# CORS +FRONTEND_URL=https://she-wants.vercel.app +``` + +--- + +## ๐Ÿ“ Pre-Deployment Checklist + +### Frontend +- [ ] Build succeeds (`npm run build`) +- [ ] API URL updated for production +- [ ] Environment variables configured +- [ ] CORS settings updated +- [ ] All dependencies in package.json + +### Backend +- [ ] Database path configured +- [ ] CORS allows frontend URL +- [ ] Port configuration correct +- [ ] All routes tested +- [ ] Error handling in place + +### Database +- [ ] SQLite file included or auto-created +- [ ] Initial data seeded (if needed) +- [ ] Backup strategy in place + +--- + +## ๐Ÿš€ Quick Deploy Script + +Create `deploy.sh`: + +```bash +#!/bin/bash + +echo "๐Ÿš€ Starting deployment..." + +# Build frontend +echo "๐Ÿ“ฆ Building frontend..." +npm run build + +# Deploy to Vercel +echo "๐ŸŒ Deploying to Vercel..." +vercel --prod + +# Deploy backend to Render +echo "๐Ÿ”ง Backend deployment..." +echo "Please deploy backend manually at https://render.com" + +echo "โœ… Deployment complete!" +echo "Frontend: Check Vercel dashboard" +echo "Backend: Check Render dashboard" +``` + +Make it executable: +```bash +chmod +x deploy.sh +./deploy.sh +``` + +--- + +## ๐ŸŒ Your Deployed URLs + +After deployment, update your README.md: + +```markdown +### Hosted Project Link +- **Frontend**: https://she-wants.vercel.app +- **Backend API**: https://she-wants-backend.onrender.com +- **Demo Video**: [Your YouTube link] +``` + +--- + +## ๐Ÿ” Testing Your Deployed App + +### Test Frontend +1. Open your Vercel URL +2. Check if calculator loads +3. Try logging in +4. Test all features + +### Test Backend +```bash +# Test API endpoint +curl https://she-wants-backend.onrender.com/api/helpers + +# Test login +curl -X POST https://she-wants-backend.onrender.com/api/auth/login \ + -H "Content-Type: application/json" \ + -d '{"username":"testuser","password":"password123"}' +``` + +--- + +## โš ๏ธ Common Deployment Issues + +### Issue 1: "Cannot connect to backend" +**Solution:** +- Check CORS settings in server/index.js +- Verify API URL in src/config/api.js +- Check backend is running on Render + +### Issue 2: "Database not found" +**Solution:** +- Ensure database.js creates tables on startup +- Check file permissions +- Use persistent storage on Render + +### Issue 3: "Build fails" +**Solution:** +- Run `npm run build` locally first +- Check for missing dependencies +- Verify Node.js version matches + +### Issue 4: "Google Maps not working" +**Solution:** +- Ensure HTTPS is enabled (required for geolocation) +- Check browser permissions +- Verify location API is accessible + +--- + +## ๐Ÿ’ฐ Cost Breakdown + +### Free Tier Limits + +| Service | Free Tier | Limits | +|---------|-----------|--------| +| **Vercel** | โœ… Free | 100GB bandwidth/month | +| **Render** | โœ… Free | 750 hours/month, sleeps after 15min inactive | +| **Netlify** | โœ… Free | 100GB bandwidth/month | +| **Railway** | โœ… $5 credit | Limited hours | +| **Heroku** | โŒ Paid | No free tier anymore | + +**Recommended:** Vercel (Frontend) + Render (Backend) = **100% FREE** + +--- + +## ๐ŸŽฌ Next Steps After Deployment + +1. **Test Everything** + - All features working + - Location permissions + - Google Maps integration + - Database operations + +2. **Update README** + - Add hosted links + - Add screenshots + - Add demo video + +3. **Monitor** + - Check Vercel analytics + - Monitor Render logs + - Watch for errors + +4. **Optimize** + - Enable caching + - Compress images + - Minify code + +--- + +## ๐Ÿ“Š Deployment Status Dashboard + +Create this in your README: + +```markdown +## ๐ŸŒ Live Demo + +| Service | Status | URL | +|---------|--------|-----| +| Frontend | ๐ŸŸข Live | https://she-wants.vercel.app | +| Backend | ๐ŸŸข Live | https://she-wants-backend.onrender.com | +| Database | ๐ŸŸข Active | SQLite on Render | +``` + +--- + +## ๐ŸŽฏ Recommended: Vercel + Render + +**Why this combo?** +- โœ… 100% Free +- โœ… Automatic HTTPS +- โœ… Easy deployment +- โœ… Good performance +- โœ… Auto-scaling +- โœ… CI/CD built-in + +**Deployment time:** ~10 minutes + +--- + +## ๐Ÿ“ž Need Help? + +If deployment fails: +1. Check deployment logs +2. Verify all environment variables +3. Test locally first +4. Check CORS settings +5. Ensure database is accessible + +--- + +**Ready to deploy?** Start with Option 1 (Vercel + Render) for the easiest experience! ๐Ÿš€ diff --git a/DEPLOY_BUTTON.md b/DEPLOY_BUTTON.md new file mode 100644 index 000000000..9e6178fd3 --- /dev/null +++ b/DEPLOY_BUTTON.md @@ -0,0 +1,16 @@ +# Deploy to Vercel + +Click the button below to deploy the frontend to Vercel: + +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/YOUR_USERNAME/SHE_WANTS) + +## After Deployment + +1. Your frontend will be live at: `https://your-project.vercel.app` +2. Deploy the backend to Render following [DEPLOY_NOW.md](DEPLOY_NOW.md) +3. Update the `VITE_API_URL` environment variable in Vercel with your Render backend URL + +## Environment Variables + +Add these in Vercel: +- `VITE_API_URL`: Your Render backend URL (e.g., `https://she-wants-backend.onrender.com`) diff --git a/DEPLOY_EASY.md b/DEPLOY_EASY.md new file mode 100644 index 000000000..62f522b1d --- /dev/null +++ b/DEPLOY_EASY.md @@ -0,0 +1,164 @@ +# ๐Ÿš€ Deploy to Vercel - Easy Website Method + +## โœ… Easiest Way to Deploy (No CLI needed!) + +### Step 1: Push Your Code to GitHub + +```bash +cd /Users/macbookair/Desktop/SHE_WANTS + +# Initialize git (if not done) +git init + +# Add all files +git add . + +# Commit +git commit -m "Ready for deployment" +``` + +**Then create a GitHub repository:** +1. Go to https://github.com/new +2. Repository name: `SHE_WANTS` +3. Make it Public +4. Click "Create repository" +5. Copy the commands shown and run them + +**OR if you already have a GitHub repo, just push:** +```bash +git remote add origin https://github.com/YOUR_USERNAME/SHE_WANTS.git +git branch -M main +git push -u origin main +``` + +--- + +### Step 2: Deploy to Vercel (Website Method) + +1. **Go to Vercel**: https://vercel.com +2. **Sign Up/Login**: Click "Sign Up" โ†’ Choose "Continue with GitHub" +3. **Authorize**: Allow Vercel to access your GitHub +4. **Import Project**: + - Click "Add New..." โ†’ "Project" + - Find your `SHE_WANTS` repository + - Click "Import" +5. **Configure**: + - **Framework Preset**: Vite (should auto-detect) + - **Root Directory**: `./` + - **Build Command**: `npm run build` + - **Output Directory**: `dist` + - **Install Command**: `npm install` +6. **Environment Variables** (Click "Add"): + - Name: `VITE_API_URL` + - Value: `http://localhost:3000` (we'll update this later) +7. **Click "Deploy"** + +**Wait 2-3 minutes...** + +--- + +### Step 3: Get Your Live URL + +After deployment completes, you'll see: +``` +๐ŸŽ‰ Congratulations! Your project has been deployed. +``` + +**Your URL will be something like:** +- `https://she-wants.vercel.app` +- or `https://she-wants-riya.vercel.app` + +**Copy this URL!** + +--- + +## ๐Ÿ“ฑ Alternative: Deploy Without GitHub + +If you don't want to use GitHub: + +### Method 1: Drag and Drop + +1. Make sure your build is ready: + ```bash + npm run build + ``` + +2. Go to https://vercel.com +3. Sign up/Login +4. Click "Add New..." โ†’ "Project" +5. **Drag and drop** the `dist` folder onto the page +6. Vercel will deploy it instantly! + +**Your site will be live in ~1 minute!** + +--- + +## ๐Ÿ”ง After Deployment + +### Update Your README + +Add your live URL to `README.md`: + +```markdown +### Hosted Project Link +https://she-wants.vercel.app +``` + +### Test Your Deployment + +1. Open your Vercel URL +2. Check if calculator loads +3. Click "Next" +4. Try logging in + +--- + +## ๐Ÿ› If You See "Deployment Not Found" + +This error usually means: +1. You're trying to access a deployment that doesn't exist yet +2. The URL is incorrect + +**Solution:** +- Use the website method above +- The deployment will be created fresh +- You'll get a new URL + +--- + +## ๐Ÿ“Š What You Get + +โœ… **Live URL**: Your app is online! +โœ… **HTTPS**: Automatic SSL certificate +โœ… **CDN**: Fast loading worldwide +โœ… **Auto-deploy**: Updates on every git push +โœ… **Free**: No credit card needed + +--- + +## ๐ŸŽฏ Quick Summary + +**Fastest method:** +1. Build: `npm run build` +2. Go to: https://vercel.com +3. Drag `dist` folder +4. Done! โœ… + +**Best method (with GitHub):** +1. Push code to GitHub +2. Import to Vercel +3. Click Deploy +4. Done! โœ… + +--- + +## ๐Ÿ“ž Need Help? + +If you're stuck: +1. Make sure you're logged into Vercel +2. Try the drag-and-drop method (easiest!) +3. Check that `npm run build` works locally + +--- + +**Ready?** Go to https://vercel.com and let's deploy! ๐Ÿš€ diff --git a/DEPLOY_NOW.md b/DEPLOY_NOW.md new file mode 100644 index 000000000..4a1962cac --- /dev/null +++ b/DEPLOY_NOW.md @@ -0,0 +1,259 @@ +# ๐Ÿš€ SHE_WANTS - Quick Deployment Instructions + +## โœ… Your App is Ready to Deploy! + +The build completed successfully. Here's how to deploy it: + +--- + +## ๐ŸŒŸ FASTEST METHOD: Vercel (Frontend) + Render (Backend) + +### Part 1: Deploy Frontend to Vercel (5 minutes) + +#### Option A: Using Vercel CLI (Recommended) + +```bash +# 1. Install Vercel CLI +npm install -g vercel + +# 2. Login to Vercel (opens browser) +vercel login + +# 3. Deploy from your project folder +cd /Users/macbookair/Desktop/SHE_WANTS +vercel --prod +``` + +**Follow the prompts:** +- Set up and deploy? **Yes** +- Which scope? **Your account** +- Link to existing project? **No** +- Project name? **she-wants** (or your choice) +- Directory? **./** (press Enter) +- Override settings? **No** + +**You'll get a URL like:** `https://she-wants.vercel.app` + +#### Option B: Using Vercel Website + +1. Go to https://vercel.com +2. Click "Sign Up" or "Login" (use GitHub) +3. Click "Add New..." โ†’ "Project" +4. Click "Import Git Repository" +5. If not connected, connect your GitHub account +6. Select your SHE_WANTS repository +7. Configure: + - **Framework Preset**: Vite + - **Root Directory**: ./ + - **Build Command**: `npm run build` + - **Output Directory**: `dist` +8. Add Environment Variable: + - **Name**: `VITE_API_URL` + - **Value**: `https://she-wants-backend.onrender.com` (we'll create this next) +9. Click "Deploy" + +**Wait 2-3 minutes for deployment to complete.** + +--- + +### Part 2: Deploy Backend to Render (10 minutes) + +#### Step 1: Push Your Code to GitHub (if not already) + +```bash +cd /Users/macbookair/Desktop/SHE_WANTS + +# Initialize git if not already done +git init + +# Add all files +git add . + +# Commit +git commit -m "Ready for deployment" + +# Create GitHub repository and push +# (Follow GitHub instructions to create a new repository) +git remote add origin https://github.com/YOUR_USERNAME/SHE_WANTS.git +git branch -M main +git push -u origin main +``` + +#### Step 2: Deploy to Render + +1. Go to https://render.com +2. Click "Sign Up" or "Login" (use GitHub) +3. Click "New +" โ†’ "Web Service" +4. Click "Connect GitHub" and authorize Render +5. Select your **SHE_WANTS** repository +6. Configure: + - **Name**: `she-wants-backend` + - **Region**: Choose closest to you + - **Branch**: `main` + - **Root Directory**: Leave empty + - **Runtime**: `Node` + - **Build Command**: `npm install` + - **Start Command**: `node server/index.js` + - **Instance Type**: **Free** +7. Click "Advanced" and add Environment Variables: + - **NODE_ENV**: `production` + - **FRONTEND_URL**: `https://she-wants.vercel.app` (your Vercel URL) +8. Click "Create Web Service" + +**Wait 5-10 minutes for deployment.** + +**You'll get a URL like:** `https://she-wants-backend.onrender.com` + +#### Step 3: Update Frontend with Backend URL + +1. Go back to Vercel dashboard +2. Select your project +3. Go to "Settings" โ†’ "Environment Variables" +4. Edit `VITE_API_URL`: + - **Value**: `https://she-wants-backend.onrender.com` (your Render URL) +5. Go to "Deployments" +6. Click "..." on latest deployment โ†’ "Redeploy" + +--- + +## ๐ŸŽฏ Alternative: Netlify (If Vercel doesn't work) + +### Deploy to Netlify + +```bash +# 1. Install Netlify CLI +npm install -g netlify-cli + +# 2. Login +netlify login + +# 3. Deploy +cd /Users/macbookair/Desktop/SHE_WANTS +netlify deploy --prod --dir=dist +``` + +**Follow prompts:** +- Create new site? **Yes** +- Team? **Your account** +- Site name? **she-wants** + +**You'll get:** `https://she-wants.netlify.app` + +--- + +## ๐Ÿ“ After Deployment Checklist + +### Test Your Deployed App + +1. **Open your frontend URL** (e.g., `https://she-wants.vercel.app`) +2. **Check calculator loads** +3. **Click "Next" button** +4. **Try logging in** with: + - Username: `testuser` + - Password: `password123` +5. **Test features:** + - Period Tracker + - Pad Request + - Nearby Requests + - Community Support + - Sisterhood Chats + +### Update Your README + +Add your hosted links to README.md: + +```markdown +### Hosted Project Link +- **Live App**: https://she-wants.vercel.app +- **Backend API**: https://she-wants-backend.onrender.com +``` + +--- + +## ๐Ÿ› Troubleshooting + +### Frontend shows "Cannot connect to backend" + +**Solution:** +1. Check if backend is deployed and running on Render +2. Verify `VITE_API_URL` environment variable in Vercel +3. Check browser console for errors +4. Verify CORS settings in server/index.js + +### Backend deployment fails + +**Solution:** +1. Check Render logs for errors +2. Verify `package.json` has all dependencies +3. Ensure `node server/index.js` works locally +4. Check Node.js version compatibility + +### Database errors + +**Solution:** +- Render automatically creates the SQLite database +- Check if `server/database.js` runs on startup +- Verify file permissions + +--- + +## ๐Ÿ’ฐ Cost + +**Total Cost: $0 (100% FREE)** + +- Vercel Free Tier: 100GB bandwidth/month +- Render Free Tier: 750 hours/month +- No credit card required for either! + +--- + +## โฑ๏ธ Deployment Time + +- **Vercel (Frontend)**: ~3 minutes +- **Render (Backend)**: ~10 minutes +- **Total**: ~15 minutes + +--- + +## ๐ŸŽ‰ You're Done! + +Once deployed, you'll have: +- โœ… Live frontend URL +- โœ… Live backend API +- โœ… Automatic HTTPS +- โœ… Auto-deploy on git push +- โœ… Free hosting + +**Share your link:** `https://she-wants.vercel.app` + +--- + +## ๐Ÿ“ž Need Help? + +If you encounter issues: +1. Check deployment logs in Vercel/Render dashboard +2. Test locally first: `npm run dev` +3. Verify all environment variables +4. Check CORS settings + +--- + +## ๐Ÿš€ Quick Commands Reference + +```bash +# Build locally +npm run build + +# Deploy to Vercel +vercel --prod + +# Deploy to Netlify +netlify deploy --prod --dir=dist + +# Check if backend is running +curl https://she-wants-backend.onrender.com/api/helpers +``` + +--- + +**Ready to deploy?** Start with Vercel CLI - it's the fastest! ๐ŸŽฏ diff --git a/FEATURES.md b/FEATURES.md new file mode 100644 index 000000000..502ddd77b --- /dev/null +++ b/FEATURES.md @@ -0,0 +1,188 @@ +# SHE WANTS - Complete Feature Summary + +## โœ… Implemented Features + +### 1. **Calculator Entry Point** ๐Ÿงฎ +- **Status**: โœ… Fully Implemented +- **Description**: Disguised calculator interface as the first screen +- **Features**: + - Functional calculator for basic math operations + - Secret code entry: `1234=` to access the app + - "Next" button for new users to easily navigate to signup/login + - Hint text: "๐Ÿ’ก Hint: Or enter 1234= on the calculator" + - Welcome message for returning users + +### 2. **Authentication System** ๐Ÿ” +- **Status**: โœ… Fully Implemented +- **Backend**: `/api/auth/register`, `/api/auth/login` +- **Features**: + - User registration with username, password, and secret code + - User login with credentials + - Secret code validation (default: 1234=) + - Form state management with proper validation + - Toggle between login and signup modes + +### 3. **Period Tracker** ๐ŸŒธ +- **Status**: โœ… Fully Implemented & Enhanced +- **Backend**: `/api/cycles/:userId`, `/api/cycles`, `/api/cycles/:cycleId` +- **Features**: + - Log period start dates + - View cycle history (last 5 cycles) + - **Predictions**: + - Next period expected date + - Days until next period + - Current menstrual phase (Menstrual, Follicular, Ovulation, Luteal) + - **Statistics**: + - Average cycle length calculation + - Total cycles tracked + - **UI Enhancements**: + - Beautiful gradient design + - Prediction box with calendar icon + - Cycle timeline with dots + - "Latest" badge for most recent cycle + - Days ago calculation for each cycle + - **Backend Features**: + - Duplicate prevention (can't log same date twice) + - Cycle deletion endpoint + - Statistics calculation + +### 4. **Sanitary Pad Request System** ๐Ÿฉธ +- **Status**: โœ… Fully Implemented +- **Backend**: `/api/pad-request`, `/api/pad-requests/nearby/:userId`, `/api/pad-requests/my/:userId`, `/api/pad-request/fulfill` +- **Features**: + - **Request Pads**: + - Request sanitary pads with current GPS location + - Location sharing with nearby users + - Real-time geolocation access + - **Nearby Requests**: + - View active requests from other users + - See username, location coordinates, and time + - "Help ๐Ÿ’" button to fulfill requests + - Distance calculation using Haversine formula + - Google Maps integration for directions + - Auto-refresh every 30 seconds + - Manual refresh button + - **Backend**: + - Store requests with location data + - Track request status (active/fulfilled) + - Record who fulfilled each request + - Filter out user's own requests from nearby list + +### 5. **Community Support System** ๐Ÿ’ +- **Status**: โœ… Fully Implemented (NEW!) +- **Backend**: `/api/helpers/register`, `/api/helpers`, `/api/helpers/status/:userId`, `/api/helpers/availability`, `/api/helpers/:userId` +- **Features**: + - **Become a Helper**: + - Register as a community helper + - Add optional bio describing how you can help + - Share location (optional) + - Availability toggle (Available/Unavailable) + - **Helper Management**: + - View your helper status + - Toggle availability on/off + - Remove helper status + - Update bio and information + - **Find Helpers**: + - View all available helpers in the community + - See helper bios and availability + - Location indicators for helpers + - Real-time helper count + - **Backend**: + - Community helpers database table + - UNIQUE constraint (one helper entry per user) + - Availability management + - Helper registration with conflict handling (ON CONFLICT DO UPDATE) + +### 6. **Dashboard** ๐Ÿ“Š +- **Status**: โœ… Fully Implemented +- **Features**: + - User-specific welcome message + - Lock & Logout button + - All feature components integrated: + - Period Tracker + - Pad Request + - Nearby Requests + - Community Support + - Clean card-based layout + - Responsive design + +## ๐Ÿ—„๏ธ Database Schema + +### Tables: +1. **users** - User accounts +2. **cycles** - Period tracking data +3. **emergency_contacts** - Emergency contacts (placeholder) +4. **pad_requests** - Sanitary pad requests with location +5. **community_helpers** - Community helpers registry (NEW!) + +## ๐ŸŽจ UI/UX Highlights + +- **Color Scheme**: Pink/purple gradient theme +- **Design**: Modern, clean, card-based layout +- **Animations**: Smooth transitions and hover effects +- **Icons**: Emoji-based visual indicators +- **Responsive**: Mobile-friendly design +- **Accessibility**: Clear labels and intuitive navigation + +## ๐Ÿ”’ Security Features + +- Secret code protection (calculator disguise) +- User-specific secret codes +- Lock screen functionality +- Session management + +## ๐Ÿ“ฑ User Flow + +1. **First Visit**: Calculator โ†’ Click "Next" โ†’ Signup โ†’ Dashboard +2. **Returning User**: Calculator โ†’ Enter secret code โ†’ Dashboard +3. **Logout**: Dashboard โ†’ Lock & Logout โ†’ Calculator (with user context) + +## ๐Ÿš€ How to Use + +### Start the Application: +```bash +# Terminal 1 - Backend Server +npm run server:dev + +# Terminal 2 - Frontend Dev Server +npm run dev +``` + +### Access the App: +- Open: `http://localhost:5173/` +- Default secret code: `1234=` + +## ๐Ÿ“ API Endpoints Summary + +### Authentication +- `POST /api/auth/register` - Register new user +- `POST /api/auth/login` - Login user + +### Period Tracker +- `GET /api/cycles/:userId` - Get user's cycles with statistics +- `POST /api/cycles` - Log new period +- `DELETE /api/cycles/:cycleId` - Delete a cycle + +### Pad Requests +- `POST /api/pad-request` - Create pad request +- `GET /api/pad-requests/nearby/:userId` - Get nearby requests +- `GET /api/pad-requests/my/:userId` - Get user's requests +- `POST /api/pad-request/fulfill` - Mark request as fulfilled + +### Community Helpers (NEW!) +- `POST /api/helpers/register` - Register as helper +- `GET /api/helpers` - Get all available helpers +- `GET /api/helpers/status/:userId` - Check if user is a helper +- `PUT /api/helpers/availability` - Update availability +- `DELETE /api/helpers/:userId` - Remove helper status + +## โœจ Recent Enhancements + +1. **Calculator "Next" Button** - Easy navigation for new users +2. **Period Tracker Predictions** - Smart cycle predictions and phase tracking +3. **Community Support System** - Complete helper registration and management +4. **Enhanced Backend** - Comprehensive validation and error handling + +--- + +**Made with โค๏ธ for women's safety and health** diff --git a/GOOGLE_MAPS_INTEGRATION.md b/GOOGLE_MAPS_INTEGRATION.md new file mode 100644 index 000000000..6bf9653d6 --- /dev/null +++ b/GOOGLE_MAPS_INTEGRATION.md @@ -0,0 +1,171 @@ +# โœ… Google Maps Integration - WORKING! + +## ๐ŸŽฏ Summary + +The Google Maps integration is **FULLY FUNCTIONAL** for the Nearby Requests feature. Here's what's working: + +--- + +## ๐Ÿ—บ๏ธ Features Working + +### 1. **"View on Map" Button** โœ… +- **Location**: On each nearby request card +- **Function**: Opens Google Maps with the exact location +- **URL Format**: `https://www.google.com/maps/search/?api=1&query=LAT,LNG` +- **Behavior**: Opens in new tab +- **Status**: โœ… **WORKING** + +### 2. **"Help ๐Ÿ’" Button** โœ… +- **Location**: On each nearby request card +- **Function**: + 1. Gets your current location + 2. Calculates distance to requester + 3. Shows confirmation dialog + 4. Marks request as fulfilled in database + 5. Opens Google Maps with directions from your location to theirs +- **URL Format**: `https://www.google.com/maps/dir/?api=1&origin=YOUR_LAT,YOUR_LNG&destination=THEIR_LAT,THEIR_LNG&travelmode=driving` +- **Behavior**: Opens in new tab with turn-by-turn directions +- **Status**: โœ… **WORKING** + +--- + +## ๐Ÿ”ง Backend API + +### Endpoint: `POST /api/pad-request/fulfill` +**Status**: โœ… **WORKING** + +**Request Body**: +```json +{ + "requestId": 16, + "fulfilledBy": 1 +} +``` + +**Response**: +```json +{ + "message": "Request marked as fulfilled!" +} +``` + +**Database Update**: +```sql +UPDATE pad_requests +SET status = 'fulfilled', fulfilled_by = 1 +WHERE id = 16 +``` + +--- + +## ๐Ÿ“ฑ How It Works + +### Scenario 1: Just View Location +1. User sees a nearby request +2. Clicks **"๐Ÿ—บ๏ธ View on Map"** +3. Google Maps opens showing the location +4. No database changes + +### Scenario 2: Help Someone +1. User sees a nearby request +2. Clicks **"Help ๐Ÿ’"** +3. Browser requests location permission +4. System calculates distance +5. Confirmation dialog shows: "Help [username]? They are X km away" +6. User clicks OK +7. Request marked as fulfilled in database +8. Google Maps opens with directions +9. Request disappears from nearby list (because it's fulfilled) + +--- + +## ๐Ÿงช Test Results + +### Backend API Test โœ… +```bash +curl -X POST http://localhost:3000/api/pad-request/fulfill \ + -H "Content-Type: application/json" \ + -d '{"requestId": 16, "fulfilledBy": 1}' + +Response: {"message": "Request marked as fulfilled!"} +``` + +### Frontend Test โœ… +- โœ… "View on Map" button opens Google Maps +- โœ… "Help ๐Ÿ’" button requests location +- โœ… Distance calculation works +- โœ… Confirmation dialog appears +- โœ… Database update successful +- โœ… Google Maps opens with directions +- โœ… Request list refreshes + +--- + +## ๐Ÿ” Console Logs (for debugging) + +When you click "Help ๐Ÿ’", you'll see these logs: +```javascript +Help button clicked for request: {id: 16, user_id: 7, ...} +Getting current position... +My location: 10.8242, 76.6424 +Request location: 10.8244, 76.6422 +Distance calculated: 0.2 km +User confirmed help +Marking request as fulfilled... +Request marked as fulfilled +Opening Google Maps URL: https://www.google.com/maps/dir/?api=1&origin=... +Google Maps opened successfully +``` + +--- + +## ๐Ÿšจ Troubleshooting + +### If Google Maps doesn't open: +1. **Check popup blocker** - Allow popups for localhost:5173 +2. **Check browser console** - Look for errors +3. **Check location permissions** - Allow location access + +### If "Help" button doesn't work: +1. **Enable location services** - Browser needs location permission +2. **Check console logs** - See detailed error messages +3. **Check network tab** - Verify API call to `/api/pad-request/fulfill` + +--- + +## ๐Ÿ“Š Current Database State + +Active pad requests from user `riyarose05@gmail.com`: +- Request #16: Location (10.8244, 76.6422) +- Request #15: Location (10.8244, 76.6422) +- Request #14: Location (10.8244, 76.6422) +- ... and 9 more requests + +All visible to other users in the "Nearby Requests" section. + +--- + +## โœจ Improvements Made + +1. **Better error handling** - Specific error messages for location issues +2. **Console logging** - Detailed logs for debugging +3. **Popup fallback** - If popup blocked, shows manual link +4. **Two button options**: + - Quick view: "View on Map" + - Full help: "Help ๐Ÿ’" +5. **Origin + Destination** - Google Maps shows full route +6. **Travel mode** - Set to "driving" for best routes + +--- + +## ๐ŸŽ‰ Conclusion + +**Everything is working!** + +- โœ… Backend API functional +- โœ… Frontend buttons working +- โœ… Google Maps integration complete +- โœ… Database updates successful +- โœ… Location services integrated + +The feature is **production-ready**! ๐Ÿš€ diff --git a/INSTALLATION.md b/INSTALLATION.md new file mode 100644 index 000000000..f6d8c019b --- /dev/null +++ b/INSTALLATION.md @@ -0,0 +1,446 @@ +# ๐ŸŒธ SHE_WANTS - Installation & Deployment Guide + +## ๐Ÿ“‹ Table of Contents +1. [System Requirements](#system-requirements) +2. [Installation Steps](#installation-steps) +3. [Running the Application](#running-the-application) +4. [Deployment Options](#deployment-options) +5. [Environment Variables](#environment-variables) +6. [Troubleshooting](#troubleshooting) + +--- + +## ๐Ÿ–ฅ๏ธ System Requirements + +### Minimum Requirements +- **Operating System**: Windows 10+, macOS 10.14+, or Linux (Ubuntu 18.04+) +- **Node.js**: Version 16.x or higher +- **npm**: Version 8.x or higher (comes with Node.js) +- **RAM**: 2GB minimum, 4GB recommended +- **Disk Space**: 500MB free space +- **Browser**: Chrome 90+, Firefox 88+, Safari 14+, or Edge 90+ + +### Check Your Current Versions +```bash +node --version # Should show v16.x.x or higher +npm --version # Should show 8.x.x or higher +``` + +--- + +## ๐Ÿ“ฆ Installation Steps + +### 1. **Install Node.js and npm** + +#### On macOS: +```bash +# Using Homebrew +brew install node + +# Or download from https://nodejs.org/ +``` + +#### On Windows: +```bash +# Download installer from https://nodejs.org/ +# Run the installer and follow the prompts +``` + +#### On Linux (Ubuntu/Debian): +```bash +curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - +sudo apt-get install -y nodejs +``` + +### 2. **Clone or Download the Project** + +```bash +# If you have the project folder +cd /path/to/SHE_WANTS + +# Or if downloading from repository +git clone +cd SHE_WANTS +``` + +### 3. **Install Dependencies** + +```bash +# Install all required packages +npm install +``` + +This will install: +- **Frontend**: React, Vite, Axios +- **Backend**: Express, SQLite3, CORS, Body-parser +- **Dev Tools**: Nodemon, Concurrently + +### 4. **Initialize Database** + +The database will be automatically created when you first run the server. It includes: +- Users table +- Cycles table (period tracking) +- Pad requests table +- Community helpers table +- Sisterhood posts, comments, and likes tables + +--- + +## ๐Ÿš€ Running the Application + +### Development Mode (Recommended for Testing) + +```bash +# Start both frontend and backend servers +npm run dev +``` + +This command runs: +- **Frontend**: http://localhost:5173 (Vite dev server) +- **Backend**: http://localhost:3000 (Express API server) + +### Run Servers Separately + +```bash +# Terminal 1: Start backend only +npm run server:dev + +# Terminal 2: Start frontend only +npm run client:dev +``` + +### Production Build + +```bash +# Build the frontend for production +npm run build + +# The built files will be in the 'dist' folder +# You can serve these with any static file server +``` + +--- + +## ๐ŸŒ Deployment Options + +### Option 1: Deploy to Vercel (Frontend) + Railway (Backend) + +#### Frontend (Vercel): +```bash +# Install Vercel CLI +npm install -g vercel + +# Build and deploy +npm run build +vercel --prod +``` + +#### Backend (Railway): +1. Go to https://railway.app +2. Create new project +3. Connect your GitHub repository +4. Set environment variables +5. Deploy + +### Option 2: Deploy to Heroku (Full Stack) + +```bash +# Install Heroku CLI +npm install -g heroku + +# Login to Heroku +heroku login + +# Create new app +heroku create she-wants-app + +# Deploy +git push heroku main +``` + +### Option 3: Deploy to VPS (DigitalOcean, AWS, etc.) + +```bash +# On your VPS: +# 1. Install Node.js +curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - +sudo apt-get install -y nodejs + +# 2. Clone your project +git clone +cd SHE_WANTS + +# 3. Install dependencies +npm install + +# 4. Install PM2 (process manager) +sudo npm install -g pm2 + +# 5. Start the application +pm2 start npm --name "she-wants-backend" -- run server:dev +pm2 start npm --name "she-wants-frontend" -- run client:dev + +# 6. Make it start on boot +pm2 startup +pm2 save + +# 7. Setup Nginx as reverse proxy (optional) +sudo apt install nginx +# Configure nginx to proxy to localhost:5173 and localhost:3000 +``` + +### Option 4: Docker Deployment + +Create `Dockerfile`: +```dockerfile +FROM node:18-alpine + +WORKDIR /app + +COPY package*.json ./ +RUN npm install + +COPY . . + +EXPOSE 3000 5173 + +CMD ["npm", "run", "dev"] +``` + +Create `docker-compose.yml`: +```yaml +version: '3.8' +services: + app: + build: . + ports: + - "3000:3000" + - "5173:5173" + volumes: + - ./server/shewants.db:/app/server/shewants.db +``` + +Run: +```bash +docker-compose up -d +``` + +--- + +## ๐Ÿ” Environment Variables + +Create a `.env` file in the root directory: + +```env +# Server Configuration +PORT=3000 +NODE_ENV=production + +# Database +DB_PATH=./server/shewants.db + +# Frontend URL (for CORS) +FRONTEND_URL=http://localhost:5173 + +# Session Secret (for production) +SESSION_SECRET=your-secret-key-here + +# Google Maps API (if needed for enhanced features) +GOOGLE_MAPS_API_KEY=your-api-key-here +``` + +--- + +## ๐Ÿ“ฑ Browser Requirements + +### Required Browser Features: +- โœ… **Geolocation API** - For location-based features +- โœ… **Local Storage** - For session management +- โœ… **ES6+ Support** - Modern JavaScript +- โœ… **Fetch API** - For API calls + +### Enable Location Services: +1. **Chrome**: Settings โ†’ Privacy and Security โ†’ Site Settings โ†’ Location +2. **Firefox**: Preferences โ†’ Privacy & Security โ†’ Permissions โ†’ Location +3. **Safari**: Preferences โ†’ Websites โ†’ Location + +--- + +## ๐Ÿ› ๏ธ Troubleshooting + +### Issue: "Port 3000 already in use" +```bash +# Find and kill the process +lsof -ti:3000 | xargs kill -9 + +# Or use a different port +PORT=3001 npm run server:dev +``` + +### Issue: "Module not found" +```bash +# Clear node_modules and reinstall +rm -rf node_modules package-lock.json +npm install +``` + +### Issue: "Database locked" +```bash +# Stop all running servers +# Delete the database file +rm server/shewants.db + +# Restart the server (database will be recreated) +npm run server:dev +``` + +### Issue: "CORS errors" +- Make sure both frontend and backend are running +- Check that CORS is enabled in `server/index.js` +- Verify the API base URL in `src/config/api.js` + +### Issue: "Location not working" +- Enable location services in browser +- Use HTTPS in production (required for geolocation) +- Check browser console for permission errors + +--- + +## ๐Ÿ“Š Project Structure + +``` +SHE_WANTS/ +โ”œโ”€โ”€ src/ # Frontend React code +โ”‚ โ”œโ”€โ”€ components/ # React components +โ”‚ โ”œโ”€โ”€ config/ # API configuration +โ”‚ โ””โ”€โ”€ index.css # Styles +โ”œโ”€โ”€ server/ # Backend code +โ”‚ โ”œโ”€โ”€ index.js # Express server +โ”‚ โ”œโ”€โ”€ database.js # Database initialization +โ”‚ โ””โ”€โ”€ shewants.db # SQLite database +โ”œโ”€โ”€ public/ # Static files +โ”œโ”€โ”€ package.json # Dependencies +โ”œโ”€โ”€ vite.config.js # Vite configuration +โ””โ”€โ”€ README.md # Documentation +``` + +--- + +## ๐Ÿ”’ Security Considerations + +### For Production Deployment: + +1. **Use HTTPS**: Required for geolocation and secure data +2. **Environment Variables**: Never commit `.env` files +3. **Password Hashing**: Currently uses bcrypt (already implemented) +4. **CORS Configuration**: Restrict to your domain only +5. **Rate Limiting**: Add rate limiting to prevent abuse +6. **Input Validation**: Validate all user inputs (already implemented) +7. **SQL Injection Prevention**: Using parameterized queries (already implemented) + +### Recommended Security Additions: + +```bash +# Install security packages +npm install helmet express-rate-limit + +# Add to server/index.js: +const helmet = require('helmet'); +const rateLimit = require('express-rate-limit'); + +app.use(helmet()); + +const limiter = rateLimit({ + windowMs: 15 * 60 * 1000, // 15 minutes + max: 100 // limit each IP to 100 requests per windowMs +}); +app.use(limiter); +``` + +--- + +## ๐Ÿ“ˆ Performance Optimization + +### For Production: + +1. **Build the frontend**: + ```bash + npm run build + ``` + +2. **Serve static files from backend**: + ```javascript + // In server/index.js + app.use(express.static('dist')); + ``` + +3. **Enable compression**: + ```bash + npm install compression + ``` + ```javascript + const compression = require('compression'); + app.use(compression()); + ``` + +4. **Database optimization**: + - Add indexes to frequently queried columns + - Use connection pooling for high traffic + +--- + +## ๐Ÿ“ž Support + +### Common Commands: + +```bash +# Install dependencies +npm install + +# Run in development +npm run dev + +# Build for production +npm run build + +# Start backend only +npm run server:dev + +# Start frontend only +npm run client:dev + +# Check for updates +npm outdated + +# Update packages +npm update +``` + +--- + +## โœ… Quick Start Checklist + +- [ ] Node.js 16+ installed +- [ ] npm 8+ installed +- [ ] Project downloaded/cloned +- [ ] Dependencies installed (`npm install`) +- [ ] Servers running (`npm run dev`) +- [ ] Browser opened to http://localhost:5173 +- [ ] Location permissions enabled +- [ ] Test account created + +--- + +## ๐ŸŽ‰ You're Ready! + +Your SHE_WANTS application should now be running at: +- **Frontend**: http://localhost:5173 +- **Backend API**: http://localhost:3000 + +**Default Test Account**: +- Username: `testuser` +- Password: `password123` + +**Calculator Lock Code**: `1234=` + +Enjoy your application! ๐ŸŒธ diff --git a/README.md b/README.md index cb8e0bf95..12ef84f6c 100644 --- a/README.md +++ b/README.md @@ -1,55 +1,58 @@

- Project Banner + SHE_WANTS Banner

-# [Project Name] ๐ŸŽฏ + +# SHE WANTS ๐ŸŽฏ ## Basic Details -### Team Name: [Name] +### Team Name: [SPARKLES] ### Team Members -- Member 1: [Name] - [College] -- Member 2: [Name] - [College] +- Member 1: RIYA ROSE ROY - NSSCE PALAKKAD +- Member 2: AMJUM SHAREEF - NSSCE PALAKKAD ### Hosted Project Link -[mention your project hosted link here] +https://final-orcin-nine.vercel.app/ ### Project Description -[2-3 lines about what your project does] + +[WOMEN EMPOWERMENT - THE SITE WOULD BASED SOLUTION FOR THE ENTIRE GIRLS OF THE WORLD. THE GIRLS WOULD FACE ANXIETY, STRESS , AND DISTRESS IN THEIR PEROID TIME , SO IN ORDER TO THE MAKE SAFE . WE TEAM SPARKLES ENSURE THAT THE A SITE WHICH ENSURES THAT THE NO WOMEN WOULD FEEL UNSAFE OR BLAMED BECAUSE OF THIS REASONS . OUR MOTTO AND THEME IS FOR THAT THE WOMEN PROTECTION FOR IT.] ### The Problem statement -[What problem are you solving?] +[Many women face difficulty in managing menstrual health, especially in public spaces, colleges, workplaces, or during travel. Access to sanitary pads during emergencies is often limited, and asking for help can feel uncomfortable or unsafe. Additionally, existing period tracking applications do not provide real-time community-based emergency support while ensuring user privacy and safety.?] ### The Solution -[How are you solving it?] +[We propose a women-friendly web platform that combines period tracking with an emergency support system. The platform allows users to track their menstrual cycle while also providing a feature to request sanitary pads in urgent situations. When a user requests help, the system accesses their current location (with permission) and notifies nearby verified users who are willing to help. + +For user safety and privacy, the frontend initially appears as a simple calculator interface, ensuring discreet access. Only authenticated users can access the main features. This ensures safety, anonymity, and secure communication between users. + +The platform promotes community support, menstrual awareness, and women empowerment through technology.?] + --- ## Technical Details -### Technologies/Components Used +### Technologies/ HTML, JS, GOOGLE MAP,SQLLITE **For Software:** -- Languages used: [e.g., JavaScript, Python, Java] -- Frameworks used: [e.g., React, Django, Spring Boot] +- Languages used: [ JavaScript, Python, Java] +- Frameworks used: [ React, Django, Spring Boot] - Libraries used: [e.g., axios, pandas, JUnit] -- Tools used: [e.g., VS Code, Git, Docker] +- Tools used: [ VS Code, GIT HUB] -**For Hardware:** -- Main components: [List main components] -- Specifications: [Technical specifications] -- Tools required: [List tools needed] --- ## Features List the key features of your project: -- Feature 1: [Description] -- Feature 2: [Description] -- Feature 3: [Description] -- Feature 4: [Description] +- Feature 1: IT CONTAIN THE PEROID TRACKER FOR THE WOMEN +- Feature 2: [IT BASICALLY ADD THAT THE AND EMERGENCY BUTTON IF ANYBODY OF THE CONTAIN THE SANITARY NAPKINS IN IT] +- Feature 3: [CONTAIN THE SUPPORT SYSTEM FOR THE WOMEN NEEDED LIKE THE STRESS REILEF FOR THE USERS] +- Feature 4: [IT IS INTEGRATED WITH THE GOOGLE MAP AND HELP THE USER TO SHARE THE LOCATION] --- @@ -58,22 +61,19 @@ List the key features of your project: ### For Software: #### Installation -```bash -[Installation commands - e.g., npm install, pip install -r requirements.txt] -``` -#### Run -```bash -[Run commands - e.g., npm start, python app.py] +[Installation commands - pm install and npm run dev] ``` -### For Hardware: -#### Components Required -[List all components needed with specifications] -#### Circuit Setup -[Explain how to set up the circuit] +### Build for Production +```bash +# Build frontend +npm run build + +# Output will be in 'dist' folder +``` --- @@ -83,307 +83,86 @@ List the key features of your project: #### Screenshots (Add at least 3) -![Screenshot1](Add screenshot 1 here with proper name) +![image +](Add screenshot 1 here with proper name) *Add caption explaining what this shows* -![Screenshot2](Add screenshot 2 here with proper name) +![Screenshot2](image +) *Add caption explaining what this shows* -![Screenshot3](Add screenshot 3 here with proper name) +![Screenshot3](image +) *Add caption explaining what this shows* #### Diagrams **System Architecture:** -![Architecture Diagram](docs/architecture.png) -*Explain your system architecture - components, data flow, tech stack interaction* - -**Application Workflow:** - -![Workflow](docs/workflow.png) -*Add caption explaining your workflow* - ---- - -### For Hardware: - -#### Schematic & Circuit - -![Circuit](Add your circuit diagram here) -*Add caption explaining connections* - -![Schematic](Add your schematic diagram here) -*Add caption explaining the schematic* - -#### Build Photos - -![Team](Add photo of your team here) +**Application Workflow:**image -![Components](Add photo of your components here) -*List out all components shown* -![Build](Add photos of build process here) -*Explain the build steps* - -![Final](Add photo of final product here) -*Explain the final build* - ---- ## Additional Documentation ### For Web Projects with Backend: -#### API Documentation - -**Base URL:** `https://api.yourproject.com` - -##### Endpoints - -**GET /api/endpoint** -- **Description:** [What it does] -- **Parameters:** - - `param1` (string): [Description] - - `param2` (integer): [Description] -- **Response:** -```json -{ - "status": "success", - "data": {} -} -``` - -**POST /api/endpoint** -- **Description:** [What it does] -- **Request Body:** -```json -{ - "field1": "value1", - "field2": "value2" -} -``` -- **Response:** -```json -{ - "status": "success", - "message": "Operation completed" -} -``` - -[Add more endpoints as needed...] - ---- - -### For Mobile Apps: - -#### App Flow Diagram + API Documentation +Authentication -![App Flow](docs/app-flow.png) -*Explain the user flow through your application* +POST /api/auth/register -#### Installation Guide +POST /api/auth/logineriod Tracking -**For Android (APK):** -1. Download the APK from [Release Link] -2. Enable "Install from Unknown Sources" in your device settings: - - Go to Settings > Security - - Enable "Unknown Sources" -3. Open the downloaded APK file -4. Follow the installation prompts -5. Open the app and enjoy! +GET /api/cycles/:userId +POST /api/cycles +DELETE /api/cycles/:cycleId -**For iOS (IPA) - TestFlight:** -1. Download TestFlight from the App Store -2. Open this TestFlight link: [Your TestFlight Link] -3. Click "Install" or "Accept" -4. Wait for the app to install -5. Open the app from your home screen +Pad Requests -**Building from Source:** -```bash -# For Android -flutter build apk -# or -./gradlew assembleDebug - -# For iOS -flutter build ios -# or -xcodebuild -workspace App.xcworkspace -scheme App -configuration Debug -``` +POST /api/pad-request +GET /api/pad-requests/nearby/:userId +GET /api/pad-requests/my/:userId +POST /api/pad-request/fulfill ---- +ommunity Helpers -### For Hardware Projects: +POST /api/helpers/register +GET /api/helpers +GET /api/helpers/status/:userId +DELETE /api/helpers/:userId -#### Bill of Materials (BOM) +sisterhood Posts -| Component | Quantity | Specifications | Price | Link/Source | -|-----------|----------|----------------|-------|-------------| -| Arduino Uno | 1 | ATmega328P, 16MHz | โ‚น450 | [Link] | -| LED | 5 | Red, 5mm, 20mA | โ‚น5 each | [Link] | -| Resistor | 5 | 220ฮฉ, 1/4W | โ‚น1 each | [Link] | -| Breadboard | 1 | 830 points | โ‚น100 | [Link] | -| Jumper Wires | 20 | Male-to-Male | โ‚น50 | [Link] | -| [Add more...] | | | | | +GET /api/posts +POST /api/posts +GET /api/posts/:postId +POST /api/posts/:postId/like +GET /api/posts/:postId/liked/:userId +POST /api/posts/:postId/comment -**Total Estimated Cost:** โ‚น[Amount] -#### Assembly Instructions -**Step 1: Prepare Components** -1. Gather all components listed in the BOM -2. Check component specifications -3. Prepare your workspace -![Step 1](images/assembly-step1.jpg) -*Caption: All components laid out* -**Step 2: Build the Power Supply** -1. Connect the power rails on the breadboard -2. Connect Arduino 5V to breadboard positive rail -3. Connect Arduino GND to breadboard negative rail -![Step 2](images/assembly-step2.jpg) -*Caption: Power connections completed* -**Step 3: Add Components** -1. Place LEDs on breadboard -2. Connect resistors in series with LEDs -3. Connect LED cathodes to GND -4. Connect LED anodes to Arduino digital pins (2-6) -![Step 3](images/assembly-step3.jpg) -*Caption: LED circuit assembled* -**Step 4: [Continue for all steps...]** -**Final Assembly:** -![Final Build](images/final-build.jpg) -*Caption: Completed project ready for testing* ---- -### For Scripts/CLI Tools: -#### Command Reference - -**Basic Usage:** -```bash -python script.py [options] [arguments] -``` - -**Available Commands:** -- `command1 [args]` - Description of what command1 does -- `command2 [args]` - Description of what command2 does -- `command3 [args]` - Description of what command3 does - -**Options:** -- `-h, --help` - Show help message and exit -- `-v, --verbose` - Enable verbose output -- `-o, --output FILE` - Specify output file path -- `-c, --config FILE` - Specify configuration file -- `--version` - Show version information - -**Examples:** - -```bash -# Example 1: Basic usage -python script.py input.txt - -# Example 2: With verbose output -python script.py -v input.txt - -# Example 3: Specify output file -python script.py -o output.txt input.txt - -# Example 4: Using configuration -python script.py -c config.json --verbose input.txt -``` - -#### Demo Output - -**Example 1: Basic Processing** - -**Input:** -``` -This is a sample input file -with multiple lines of text -for demonstration purposes -``` - -**Command:** -```bash -python script.py sample.txt -``` - -**Output:** -``` -Processing: sample.txt -Lines processed: 3 -Characters counted: 86 -Status: Success -Output saved to: output.txt -``` - -**Example 2: Advanced Usage** - -**Input:** -```json -{ - "name": "test", - "value": 123 -} -``` - -**Command:** -```bash -python script.py -v --format json data.json -``` - -**Output:** -``` -[VERBOSE] Loading configuration... -[VERBOSE] Parsing JSON input... -[VERBOSE] Processing data... -{ - "status": "success", - "processed": true, - "result": { - "name": "test", - "value": 123, - "timestamp": "2024-02-07T10:30:00" - } -} -[VERBOSE] Operation completed in 0.23s -``` - ---- - -## Project Demo - -### Video -[Add your demo video link here - YouTube, Google Drive, etc.] - -*Explain what the video demonstrates - key features, user flow, technical highlights* - -### Additional Demos -[Add any extra demo materials/links - Live site, APK download, online demo, etc.] - ---- ## AI Tools Used (Optional - For Transparency Bonus) If you used AI tools during development, document them here for transparency: -**Tool Used:** [e.g., GitHub Copilot, v0.dev, Cursor, ChatGPT, Claude] +**Tool Used:** [antigravity] **Purpose:** [What you used it for] -- Example: "Generated boilerplate React components" -- Example: "Debugging assistance for async functions" -- Example: "Code review and optimization suggestions" - +- we had developed the backend for it +- **Key Prompts Used:** -- "Create a REST API endpoint for user authentication" -- "Debug this async function that's causing race conditions" +- "integrating the google map authentification" +- "real time tracking" - "Optimize this database query for better performance" **Percentage of AI-generated code:** [Approximately X%] @@ -400,9 +179,8 @@ If you used AI tools during development, document them here for transparency: ## Team Contributions -- [Name 1]: [Specific contributions - e.g., Frontend development, API integration, etc.] -- [Name 2]: [Specific contributions - e.g., Backend development, Database design, etc.] -- [Name 3]: [Specific contributions - e.g., UI/UX design, Testing, Documentation, etc.] +- [RIYA ROSE ROY]: [BACKEND - API INTEGRATION OF THE GOOGLE AMP] +- [AMJUM SHAREEF]: [FRONTEND- UI OF THE APP] --- diff --git a/REQUIREMENTS.md b/REQUIREMENTS.md new file mode 100644 index 000000000..a4c937e12 --- /dev/null +++ b/REQUIREMENTS.md @@ -0,0 +1,274 @@ +# ๐Ÿ“ฆ SHE_WANTS - Quick Installation Reference + +## โšก TL;DR - Fastest Setup + +```bash +# 1. Install Node.js from https://nodejs.org/ +# 2. Run these commands: +npm install +npm run dev +# 3. Open http://localhost:5173 +``` + +--- + +## ๐Ÿ“‹ Installation Requirements Summary + +### Required Software +| Software | Minimum Version | Download Link | +|----------|----------------|---------------| +| Node.js | 16.x | https://nodejs.org/ | +| npm | 8.x | (Included with Node.js) | + +### System Requirements +| Requirement | Minimum | Recommended | +|-------------|---------|-------------| +| RAM | 2GB | 4GB | +| Disk Space | 500MB | 1GB | +| OS | Windows 10, macOS 10.14, Ubuntu 18.04 | Latest versions | + +### Browser Requirements +- โœ… Chrome 90+ +- โœ… Firefox 88+ +- โœ… Safari 14+ +- โœ… Edge 90+ + +**Required Browser Features:** +- Geolocation API (for location-based features) +- Local Storage (for session management) +- ES6+ JavaScript support + +--- + +## ๐Ÿš€ Installation Steps + +### 1. Check if Node.js is Installed +```bash +node --version # Should show v16.x.x or higher +npm --version # Should show 8.x.x or higher +``` + +### 2. Install Node.js (if needed) + +**macOS:** +```bash +# Using Homebrew +brew install node +``` + +**Windows:** +- Download installer from https://nodejs.org/ +- Run the .msi file +- Follow installation wizard + +**Linux (Ubuntu/Debian):** +```bash +curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - +sudo apt-get install -y nodejs +``` + +### 3. Install Project Dependencies +```bash +cd /path/to/SHE_WANTS +npm install +``` + +**This installs:** +- React 18.2.0 +- Vite 5.0.8 +- Express 4.18.2 +- SQLite3 5.1.7 +- Axios 1.6.5 +- bcrypt 5.1.1 +- And all other dependencies + +### 4. Run the Application +```bash +npm run dev +``` + +**This starts:** +- Frontend server on http://localhost:5173 +- Backend API on http://localhost:3000 +- Auto-creates SQLite database + +--- + +## ๐Ÿ“ฆ Package.json Dependencies + +### Frontend Dependencies +```json +{ + "react": "^18.2.0", + "react-dom": "^18.2.0", + "axios": "^1.6.5" +} +``` + +### Backend Dependencies +```json +{ + "express": "^4.18.2", + "sqlite3": "^5.1.7", + "bcrypt": "^5.1.1", + "cors": "^2.8.5", + "body-parser": "^1.20.2" +} +``` + +### Dev Dependencies +```json +{ + "@vitejs/plugin-react": "^4.2.1", + "vite": "^5.0.8", + "nodemon": "^3.0.3", + "concurrently": "^8.2.2" +} +``` + +--- + +## ๐Ÿ”ง NPM Scripts + +| Command | Description | +|---------|-------------| +| `npm run dev` | Start both frontend and backend | +| `npm run server:dev` | Start backend only | +| `npm run client:dev` | Start frontend only | +| `npm run build` | Build frontend for production | + +--- + +## ๐ŸŒ Default Ports + +| Service | Port | URL | +|---------|------|-----| +| Frontend (Vite) | 5173 | http://localhost:5173 | +| Backend (Express) | 3000 | http://localhost:3000 | + +--- + +## ๐Ÿ—„๏ธ Database + +- **Type**: SQLite3 +- **Location**: `server/shewants.db` +- **Auto-created**: Yes (on first run) +- **Tables**: 8 tables (users, cycles, pad_requests, helpers, posts, comments, likes, etc.) + +--- + +## ๐Ÿ” Default Credentials + +**Test Account:** +- Username: `testuser` +- Password: `password123` + +**Calculator Unlock Code:** `1234=` + +--- + +## ๐Ÿ“ฑ Browser Permissions Required + +### Location Access +- Required for: Pad requests, nearby requests +- How to enable: + - Chrome: Settings โ†’ Privacy โ†’ Location + - Firefox: Preferences โ†’ Privacy โ†’ Location + - Safari: Preferences โ†’ Websites โ†’ Location + +### Popups +- Required for: Google Maps integration +- How to enable: Allow popups for localhost:5173 + +--- + +## โš ๏ธ Common Issues + +### "Port 3000 already in use" +```bash +# Kill the process using port 3000 +lsof -ti:3000 | xargs kill -9 +``` + +### "Module not found" +```bash +# Reinstall dependencies +rm -rf node_modules package-lock.json +npm install +``` + +### "Permission denied" +```bash +# Fix npm permissions (macOS/Linux) +sudo chown -R $USER ~/.npm +``` + +--- + +## ๐Ÿ“Š Disk Space Breakdown + +| Component | Size | +|-----------|------| +| node_modules | ~300MB | +| Source code | ~5MB | +| Database | ~1MB | +| Build output | ~2MB | +| **Total** | **~310MB** | + +--- + +## ๐ŸŽฏ Minimum vs Recommended Setup + +### Minimum Setup (For Testing) +- Node.js 16.x +- 2GB RAM +- 500MB disk space +- Any modern browser + +### Recommended Setup (For Development) +- Node.js 18.x or 20.x +- 4GB+ RAM +- 1GB+ disk space +- Chrome/Firefox latest version +- SSD for faster npm installs + +--- + +## ๐Ÿš€ Production Deployment + +For production deployment, see [INSTALLATION.md](INSTALLATION.md) for: +- Vercel deployment +- Heroku deployment +- VPS deployment +- Docker deployment +- Environment variables +- Security hardening + +--- + +## โœ… Installation Checklist + +- [ ] Node.js 16+ installed +- [ ] npm 8+ installed +- [ ] Project folder downloaded +- [ ] `npm install` completed successfully +- [ ] `npm run dev` running without errors +- [ ] Frontend accessible at localhost:5173 +- [ ] Backend accessible at localhost:3000 +- [ ] Can login with test credentials +- [ ] Location permission granted +- [ ] Google Maps opening correctly + +--- + +## ๐Ÿ“ž Need Help? + +See full documentation: +- [INSTALLATION.md](INSTALLATION.md) - Detailed installation guide +- [README.md](README.md) - Project overview +- [GOOGLE_MAPS_INTEGRATION.md](GOOGLE_MAPS_INTEGRATION.md) - Maps setup +- [SISTERHOOD_CHATS.md](SISTERHOOD_CHATS.md) - Forum features + +--- + +**Made with โค๏ธ for women's safety and health** diff --git a/SISTERHOOD_CHATS.md b/SISTERHOOD_CHATS.md new file mode 100644 index 000000000..1610d4293 --- /dev/null +++ b/SISTERHOOD_CHATS.md @@ -0,0 +1,280 @@ +# ๐ŸŒธ Sisterhood Chats - Complete Feature Documentation + +## โœ… Feature Overview + +**Sisterhood Chats** is a community forum where users can share experiences, seek advice, and support each other in a safe, anonymous-friendly environment. + +--- + +## ๐ŸŽฏ Key Features + +### 1. **Post Creation** +- Create posts in different categories +- Option to post anonymously +- Rich text support for sharing experiences +- Category-based organization + +### 2. **Categories** +- ๐Ÿ”ฅ **Popular** - All posts (default view) +- ๐Ÿ’” **Breakup Support** - Relationship endings and healing +- ๐Ÿ’†โ€โ™€๏ธ **Self-Care** - Mental health and wellness +- ๐Ÿฅ **Health** - Physical and reproductive health +- ๐Ÿ’• **Relationships** - Dating and relationship advice +- ๐Ÿ’ก **Advice** - General life advice +- ๐Ÿ’ฌ **General** - Everything else + +### 3. **Engagement Features** +- โค๏ธ **Like Posts** - Show support with likes +- ๐Ÿ’ฌ **Comments** - Engage in discussions +- Anonymous commenting option +- Real-time like and comment counts + +### 4. **Privacy & Safety** +- **Anonymous Posting** - Share sensitive topics without revealing identity +- **Anonymous Comments** - Comment without showing username +- User-controlled visibility + +### 5. **User Experience** +- Clean, card-based UI inspired by modern social apps +- Category filtering with color-coded badges +- Time-ago timestamps (e.g., "2h ago", "1d ago") +- Smooth animations and hover effects +- Scrollable posts list +- Post preview with "Continue reading" functionality + +--- + +## ๐Ÿ—„๏ธ Database Schema + +### Tables Created: + +#### 1. `sisterhood_posts` +```sql +- id (PRIMARY KEY) +- user_id (FOREIGN KEY โ†’ users.id) +- username (TEXT) - Display name or "Anonymous" +- category (TEXT) - Post category +- content (TEXT) - Post content +- is_anonymous (BOOLEAN) - Anonymous flag +- likes_count (INTEGER) - Total likes +- comments_count (INTEGER) - Total comments +- created_at (DATETIME) - Timestamp +``` + +#### 2. `post_comments` +```sql +- id (PRIMARY KEY) +- post_id (FOREIGN KEY โ†’ sisterhood_posts.id) +- user_id (FOREIGN KEY โ†’ users.id) +- username (TEXT) - Commenter name or "Anonymous" +- comment (TEXT) - Comment content +- is_anonymous (BOOLEAN) - Anonymous flag +- created_at (DATETIME) - Timestamp +``` + +#### 3. `post_likes` +```sql +- id (PRIMARY KEY) +- post_id (FOREIGN KEY โ†’ sisterhood_posts.id) +- user_id (FOREIGN KEY โ†’ users.id) +- created_at (DATETIME) - Timestamp +- UNIQUE(post_id, user_id) - Prevent duplicate likes +``` + +--- + +## ๐Ÿ”Œ API Endpoints + +### Posts + +#### `GET /api/posts` +Get all posts or filter by category +- **Query Params**: `category` (optional) +- **Response**: `{ posts: [...] }` + +#### `POST /api/posts` +Create a new post +- **Body**: + ```json + { + "userId": 1, + "username": "user123", + "category": "selfcare", + "content": "Post content...", + "isAnonymous": false + } + ``` +- **Response**: `{ id: 123, message: "Post created successfully" }` + +#### `GET /api/posts/:postId` +Get a single post with all comments +- **Response**: + ```json + { + "post": {...}, + "comments": [...] + } + ``` + +### Likes + +#### `POST /api/posts/:postId/like` +Like or unlike a post (toggle) +- **Body**: `{ "userId": 1 }` +- **Response**: `{ liked: true/false, message: "..." }` + +#### `GET /api/posts/:postId/liked/:userId` +Check if user liked a post +- **Response**: `{ liked: true/false }` + +### Comments + +#### `POST /api/posts/:postId/comment` +Add a comment to a post +- **Body**: + ```json + { + "userId": 1, + "username": "user123", + "comment": "Great post!", + "isAnonymous": false + } + ``` +- **Response**: `{ id: 456, message: "Comment added successfully" }` + +--- + +## ๐ŸŽจ UI Components + +### Main View +- **Header** with "New Post" button +- **Category Filter** - Horizontal scrollable pills +- **Posts List** - Scrollable feed of posts +- Each post shows: + - Username (or "Anonymous") + - Time ago + - Category badge + - Content preview (3 lines max) + - Like and comment counts + +### New Post Form +- Category dropdown +- Text area for content +- "Post anonymously" checkbox +- Submit button + +### Post Detail View +- Full post content +- Like button +- Comment form +- Comments list +- Back button to return to feed + +--- + +## ๐Ÿ’ก Usage Examples + +### Creating a Post +```javascript +// User clicks "New Post" +// Selects category: "Breakup Support" +// Writes: "Going through a tough breakup. Any advice?" +// Checks "Post anonymously" +// Clicks "Share Post" +// โ†’ Post appears in feed as "Anonymous" in Breakup Support category +``` + +### Engaging with Posts +```javascript +// User sees a post they relate to +// Clicks the post to view full content +// Clicks โค๏ธ to like +// Writes a supportive comment +// Optionally posts comment anonymously +// โ†’ Comment appears in the thread +``` + +### Filtering by Category +```javascript +// User clicks "Self-Care" category pill +// Feed updates to show only self-care posts +// User can switch to "Popular" to see all posts again +``` + +--- + +## ๐Ÿ”’ Privacy Features + +### Anonymous Posting +- When checked, username is replaced with "Anonymous" +- User ID is still stored (for moderation purposes) +- Other users cannot see who posted + +### Anonymous Comments +- Same privacy as anonymous posts +- Allows users to engage without revealing identity + +--- + +## ๐ŸŽฏ Design Inspiration + +Based on the reference images provided, the design includes: +- **Card-based layout** similar to social media feeds +- **Category pills** for easy filtering +- **Color-coded categories** for visual organization +- **Clean, modern UI** with smooth interactions +- **Mobile-friendly** responsive design + +--- + +## ๐Ÿ“Š Statistics Tracked + +- Total likes per post +- Total comments per post +- Post creation timestamps +- Comment timestamps +- User engagement (who liked what) + +--- + +## ๐Ÿš€ Future Enhancements (Potential) + +1. **Image uploads** for posts +2. **Post editing** and deletion +3. **Report/flag** inappropriate content +4. **Saved posts** feature +5. **User profiles** showing post history +6. **Trending topics** based on engagement +7. **Search functionality** +8. **Notifications** for comments on your posts + +--- + +## โœจ Integration with SHE_WANTS App + +The Sisterhood Chats feature is now fully integrated into the Dashboard: + +``` +Dashboard Components: +1. Period Tracker ๐ŸŒธ +2. Pad Request ๐Ÿฉธ +3. Nearby Requests ๐Ÿ“ +4. Community Support ๐Ÿ’ +5. Sisterhood Chats ๐Ÿ’ฌ โ† NEW! +``` + +--- + +## ๐ŸŽ‰ Complete! + +The Sisterhood Chats feature is now **fully functional** with: +- โœ… Complete backend API +- โœ… Database schema +- โœ… React component +- โœ… CSS styling +- โœ… Anonymous posting +- โœ… Likes and comments +- โœ… Category filtering +- โœ… Mobile-responsive design + +**Ready to use!** ๐Ÿš€ diff --git a/chat-support.html b/chat-support.html new file mode 100644 index 000000000..26d78083a --- /dev/null +++ b/chat-support.html @@ -0,0 +1,32 @@ + + + + + + + Chat Support - She Wants + + + + +

๐Ÿ’ฌ Sisterhood Chat

+

Community chat is under construction.

+

๐Ÿ‘ฏโ€โ™€๏ธ

+ โ† Back to Dashboard + + + \ No newline at end of file diff --git a/dashboard.html b/dashboard.html new file mode 100644 index 000000000..6884470e5 --- /dev/null +++ b/dashboard.html @@ -0,0 +1,240 @@ + + + + + + + Dashboard - She Wants + + + + +
+

๐ŸŒธ She Wants

+ +
+ + + +
+
+ Helper Mode +

Receive alerts from nearby women

+
+ +
+ + + + + + + \ No newline at end of file diff --git a/database.db b/database.db new file mode 100644 index 000000000..e69de29bb diff --git a/debug.html b/debug.html new file mode 100644 index 000000000..bdadf5510 --- /dev/null +++ b/debug.html @@ -0,0 +1,55 @@ + + + + + + Debug - She Wants + + + + +

Debug / Reset Tool

+ + + Back to Home + +

+
+    
+
+
+
\ No newline at end of file
diff --git a/emergency-support.html b/emergency-support.html
new file mode 100644
index 000000000..653b2a240
--- /dev/null
+++ b/emergency-support.html
@@ -0,0 +1,268 @@
+
+
+
+
+    
+    
+    Emergency Support - She Wants
+    
+
+
+
+    

Emergency Support

+

Press the button to alert nearby helpers

+ + + +
+
+
+ Finding nearby angels... ๐Ÿ“ก +
+
    + +
+
+ + + Back to Dashboard + + + + + + + \ No newline at end of file diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 000000000..4fa125da2 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,29 @@ +import js from '@eslint/js' +import globals from 'globals' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' +import { defineConfig, globalIgnores } from 'eslint/config' + +export default defineConfig([ + globalIgnores(['dist']), + { + files: ['**/*.{js,jsx}'], + extends: [ + js.configs.recommended, + reactHooks.configs.flat.recommended, + reactRefresh.configs.vite, + ], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + parserOptions: { + ecmaVersion: 'latest', + ecmaFeatures: { jsx: true }, + sourceType: 'module', + }, + }, + rules: { + 'no-unused-vars': ['error', { varsIgnorePattern: '^[A-Z_]' }], + }, + }, +]) diff --git a/index.html b/index.html new file mode 100644 index 000000000..6160e5519 --- /dev/null +++ b/index.html @@ -0,0 +1,16 @@ + + + + + + + + she-wants + + + +
+ + + + \ No newline at end of file diff --git a/js/auth.js b/js/auth.js new file mode 100644 index 000000000..0fd67bfef --- /dev/null +++ b/js/auth.js @@ -0,0 +1,92 @@ +/** + * She Wants - Authentication Module (Frontend Simulation) + * Handles user management and sessions using LocalStorage. + */ + +const STORAGE_KEYS = { + USERS: 'safecycle_users', + CURRENT_USER: 'safecycle_current_user' +}; + +const Auth = { + // === USERS === + getUsers: () => { + return JSON.parse(localStorage.getItem(STORAGE_KEYS.USERS) || '[]'); + }, + + saveUser: (user) => { + const users = Auth.getUsers(); + users.push(user); + localStorage.setItem(STORAGE_KEYS.USERS, JSON.stringify(users)); + return user; + }, + + findUserByEmail: (email) => { + return Auth.getUsers().find(u => u.email === email); + }, + + findUserByCode: (code) => { + return Auth.getUsers().find(u => u.uniqueCode === code); + }, + + // === AUTHENTICATION === + signup: (userData) => { + if (Auth.findUserByEmail(userData.email)) { + return { success: false, message: 'Email already registered' }; + } + + // Generate ID and Timestamp + const newUser = { + ...userData, + id: 'user_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9), + createdAt: new Date().toISOString() + }; + + Auth.saveUser(newUser); + return { success: true, user: newUser }; + }, + + login: (email, password) => { + const user = Auth.findUserByEmail(email); + if (user && user.password === password) { + Auth.setCurrentUser(user); + return { success: true, user }; + } + return { success: false, message: 'Invalid email or password' }; + }, + + loginWithCode: (code) => { + const user = Auth.findUserByCode(code); + if (user) { + Auth.setCurrentUser(user); + return { success: true, user }; + } + return { success: false, message: 'Invalid access code' }; + }, + + logout: () => { + localStorage.removeItem(STORAGE_KEYS.CURRENT_USER); + window.location.href = 'index.html'; + }, + + // === SESSION === + getCurrentUser: () => { + return JSON.parse(localStorage.getItem(STORAGE_KEYS.CURRENT_USER)); + }, + + setCurrentUser: (user) => { + // Don't save password in session for security (simulation) + const sessionUser = { ...user }; + delete sessionUser.password; + localStorage.setItem(STORAGE_KEYS.CURRENT_USER, JSON.stringify(sessionUser)); + }, + + requireAuth: () => { + if (!Auth.getCurrentUser()) { + window.location.href = 'login.html'; + } + } +}; + +// Export for global usage +window.Auth = Auth; diff --git a/js/emergency.js b/js/emergency.js new file mode 100644 index 000000000..89a71c19a --- /dev/null +++ b/js/emergency.js @@ -0,0 +1,75 @@ +/** + * She Wants - Emergency System (Frontend Simulation) + * Uses BroadcastChannel to simulate real-time alerts between tabs. + */ + +const Emergency = { + channel: new BroadcastChannel('she_wants_emergency_channel'), + + // === SENDING ALERTS === + requestHelp: (user, location) => { + const request = { + id: 'req_' + Date.now(), + user: { + id: user.id, + name: user.name, + code: user.uniqueCode + }, + location: location, // { lat, lng } + timestamp: new Date().toISOString(), + status: 'PENDING' + }; + + // Broadcast to other tabs (Helpers) + Emergency.channel.postMessage({ + type: 'HELP_REQUEST', + data: request + }); + + // Save to local history + Emergency.saveRequest(request); + return request; + }, + + respondToHelp: (requestId, helper) => { + Emergency.channel.postMessage({ + type: 'HELP_RESPONSE', + data: { + requestId, + helper: { + id: helper.id, + name: helper.name, + phone: helper.phone + } + } + }); + }, + + // === LISTENING === + listen: (onHelpRequest, onHelpResponse) => { + Emergency.channel.onmessage = (event) => { + const { type, data } = event.data; + + if (type === 'HELP_REQUEST' && onHelpRequest) { + onHelpRequest(data); + } + + if (type === 'HELP_RESPONSE' && onHelpResponse) { + onHelpResponse(data); + } + }; + }, + + // === STORAGE === + saveRequest: (request) => { + const requests = JSON.parse(localStorage.getItem('safecycle_requests') || '[]'); + requests.push(request); + localStorage.setItem('safecycle_requests', JSON.stringify(requests)); + }, + + getHistory: () => { + return JSON.parse(localStorage.getItem('safecycle_requests') || '[]'); + } +}; + +window.Emergency = Emergency; diff --git a/login.html b/login.html new file mode 100644 index 000000000..3b33c0abd --- /dev/null +++ b/login.html @@ -0,0 +1,141 @@ + + + + + + + She Wants - Login + + + + + + + + + + + \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..9e160ad51 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,5526 @@ +{ + "name": "she-wants", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "she-wants", + "version": "0.0.0", + "dependencies": { + "axios": "^1.13.5", + "cors": "^2.8.6", + "dotenv": "^17.3.1", + "express": "^5.2.1", + "nodemon": "^3.1.11", + "react": "^19.2.0", + "react-dom": "^19.2.0", + "sqlite3": "^5.1.7" + }, + "devDependencies": { + "@eslint/js": "^9.39.1", + "@types/react": "^19.2.7", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^5.1.1", + "eslint": "^9.39.1", + "eslint-plugin-react-hooks": "^7.0.1", + "eslint-plugin-react-refresh": "^0.4.24", + "globals": "^16.5.0", + "vite": "^7.3.1" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", + "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", + "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", + "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", + "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", + "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", + "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", + "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", + "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", + "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", + "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", + "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", + "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", + "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", + "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", + "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", + "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", + "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", + "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", + "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", + "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", + "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", + "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", + "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", + "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", + "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", + "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", + "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "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.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "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.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "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.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", + "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", + "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.1", + "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/eslintrc/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/@eslint/js": { + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", + "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", + "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.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "license": "MIT", + "optional": true + }, + "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/@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/@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "node_modules/@npmcli/fs/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "license": "MIT", + "optional": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz", + "integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.57.1.tgz", + "integrity": "sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.57.1.tgz", + "integrity": "sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.57.1.tgz", + "integrity": "sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.57.1.tgz", + "integrity": "sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.57.1.tgz", + "integrity": "sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.57.1.tgz", + "integrity": "sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.57.1.tgz", + "integrity": "sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.57.1.tgz", + "integrity": "sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.57.1.tgz", + "integrity": "sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.57.1.tgz", + "integrity": "sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.57.1.tgz", + "integrity": "sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.57.1.tgz", + "integrity": "sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.57.1.tgz", + "integrity": "sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.57.1.tgz", + "integrity": "sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.57.1.tgz", + "integrity": "sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.57.1.tgz", + "integrity": "sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.57.1.tgz", + "integrity": "sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.57.1.tgz", + "integrity": "sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.57.1.tgz", + "integrity": "sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.57.1.tgz", + "integrity": "sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.57.1.tgz", + "integrity": "sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.57.1.tgz", + "integrity": "sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.57.1.tgz", + "integrity": "sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.57.1.tgz", + "integrity": "sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.57.1.tgz", + "integrity": "sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/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/react": { + "version": "19.2.14", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", + "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.1.4.tgz", + "integrity": "sha512-VIcFLdRi/VYRU8OL/puL7QXMYafHmqOnwTZY50U1JPlCNj30PxCMx65c494b1K9be9hX83KVt0+gTEwTWLqToA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.29.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-rc.3", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.18.0" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "license": "ISC", + "optional": true + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "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/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agentkeepalive": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", + "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "license": "MIT", + "optional": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "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-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "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==", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/aproba": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz", + "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==", + "license": "ISC", + "optional": true + }, + "node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "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/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz", + "integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.11", + "form-data": "^4.0.5", + "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==", + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.9.19", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz", + "integrity": "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "license": "MIT", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/body-parser": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", + "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.3", + "http-errors": "^2.0.0", + "iconv-lite": "^0.7.0", + "on-finished": "^2.4.1", + "qs": "^6.14.1", + "raw-body": "^3.0.1", + "type-is": "^2.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacache": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cacache/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cacache/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", + "optional": true + }, + "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/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.30001769", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001769.tgz", + "integrity": "sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "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/chokidar/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==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "license": "MIT", + "optional": true, + "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/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "license": "ISC", + "optional": true, + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "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==", + "license": "MIT" + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "license": "ISC", + "optional": true + }, + "node_modules/content-disposition": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", + "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-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.6", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", + "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "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.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "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/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "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/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "license": "MIT", + "optional": true + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/dotenv": { + "version": "17.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.3.1.tgz", + "integrity": "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==", + "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/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.286", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz", + "integrity": "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==", + "dev": true, + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT", + "optional": true + }, + "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/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/encoding/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", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "license": "MIT", + "optional": true + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "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/esbuild": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", + "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.3", + "@esbuild/android-arm": "0.27.3", + "@esbuild/android-arm64": "0.27.3", + "@esbuild/android-x64": "0.27.3", + "@esbuild/darwin-arm64": "0.27.3", + "@esbuild/darwin-x64": "0.27.3", + "@esbuild/freebsd-arm64": "0.27.3", + "@esbuild/freebsd-x64": "0.27.3", + "@esbuild/linux-arm": "0.27.3", + "@esbuild/linux-arm64": "0.27.3", + "@esbuild/linux-ia32": "0.27.3", + "@esbuild/linux-loong64": "0.27.3", + "@esbuild/linux-mips64el": "0.27.3", + "@esbuild/linux-ppc64": "0.27.3", + "@esbuild/linux-riscv64": "0.27.3", + "@esbuild/linux-s390x": "0.27.3", + "@esbuild/linux-x64": "0.27.3", + "@esbuild/netbsd-arm64": "0.27.3", + "@esbuild/netbsd-x64": "0.27.3", + "@esbuild/openbsd-arm64": "0.27.3", + "@esbuild/openbsd-x64": "0.27.3", + "@esbuild/openharmony-arm64": "0.27.3", + "@esbuild/sunos-x64": "0.27.3", + "@esbuild/win32-arm64": "0.27.3", + "@esbuild/win32-ia32": "0.27.3", + "@esbuild/win32-x64": "0.27.3" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", + "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.39.2", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "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-plugin-react-hooks": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.1.tgz", + "integrity": "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", + "zod": "^3.25.0 || ^4.0.0", + "zod-validation-error": "^3.5.0 || ^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "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-refresh": { + "version": "0.4.26", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.26.tgz", + "integrity": "sha512-1RETEylht2O6FM/MvgnyvT+8K21wLqDNg4qD51Zj3guhjt433XbnnkVttHMyaVyAFD03QSV4LPS5iE3VQmO7XQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=8.40" + } + }, + "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.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "license": "(MIT OR WTFPL)", + "engines": { + "node": ">=6" + } + }, + "node_modules/express": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", + "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.1", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "depd": "^2.0.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/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-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/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/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/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "license": "MIT" + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", + "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", + "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": ">= 18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "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/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/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/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "license": "MIT" + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC", + "optional": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "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/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-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/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "license": "MIT" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "optional": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "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": "16.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", + "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "license": "ISC", + "optional": true + }, + "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-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/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "license": "ISC", + "optional": true + }, + "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/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "dev": true, + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hermes-estree": "0.25.1" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "license": "BSD-2-Clause", + "optional": true + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "license": "MIT", + "optional": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "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/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/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==", + "license": "ISC" + }, + "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==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "license": "ISC", + "optional": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", + "optional": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, + "node_modules/ip-address": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", + "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-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==", + "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==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "license": "MIT", + "optional": true + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "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/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "devOptional": true, + "license": "ISC" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-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": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/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/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/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/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/make-fetch-happen": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", + "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "license": "ISC", + "optional": true, + "dependencies": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/make-fetch-happen/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-fetch-happen/node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/make-fetch-happen/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", + "optional": true + }, + "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.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-fetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", + "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "license": "MIT", + "optional": true, + "dependencies": { + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "optionalDependencies": { + "encoding": "^0.1.12" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "license": "MIT" + }, + "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/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "license": "MIT" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "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/node-abi": { + "version": "3.87.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.87.0.tgz", + "integrity": "sha512-+CGM1L1CgmtheLcBuleyYOn7NWPVu0s0EJH2C4puxgEZb9h8QpR9G2dBfZJOAUhi7VQxuBPMd0hiISWcTyiYyQ==", + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-abi/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT" + }, + "node_modules/node-gyp": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", + "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "license": "MIT", + "optional": true, + "dependencies": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^9.1.0", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": ">= 10.12.0" + } + }, + "node_modules/node-gyp/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nodemon": { + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.11.tgz", + "integrity": "sha512-is96t8F/1//UHAjNPHpbsNY46ELPpftGUoSVNXwUfMk/qdjSylYrWSu1XavVTBOn526kFiOR733ATgNBCQyH0g==", + "license": "MIT", + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/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==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/nodemon/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemon/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==", + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/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/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/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=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/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.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/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/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "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/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "license": "ISC", + "optional": true + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "license": "MIT", + "optional": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "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==", + "license": "MIT" + }, + "node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/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/qs": { + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", + "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", + "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.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", + "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", + "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.4" + } + }, + "node_modules/react-refresh": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", + "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/readdirp/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "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/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "optional": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz", + "integrity": "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.57.1", + "@rollup/rollup-android-arm64": "4.57.1", + "@rollup/rollup-darwin-arm64": "4.57.1", + "@rollup/rollup-darwin-x64": "4.57.1", + "@rollup/rollup-freebsd-arm64": "4.57.1", + "@rollup/rollup-freebsd-x64": "4.57.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.57.1", + "@rollup/rollup-linux-arm-musleabihf": "4.57.1", + "@rollup/rollup-linux-arm64-gnu": "4.57.1", + "@rollup/rollup-linux-arm64-musl": "4.57.1", + "@rollup/rollup-linux-loong64-gnu": "4.57.1", + "@rollup/rollup-linux-loong64-musl": "4.57.1", + "@rollup/rollup-linux-ppc64-gnu": "4.57.1", + "@rollup/rollup-linux-ppc64-musl": "4.57.1", + "@rollup/rollup-linux-riscv64-gnu": "4.57.1", + "@rollup/rollup-linux-riscv64-musl": "4.57.1", + "@rollup/rollup-linux-s390x-gnu": "4.57.1", + "@rollup/rollup-linux-x64-gnu": "4.57.1", + "@rollup/rollup-linux-x64-musl": "4.57.1", + "@rollup/rollup-openbsd-x64": "4.57.1", + "@rollup/rollup-openharmony-arm64": "4.57.1", + "@rollup/rollup-win32-arm64-msvc": "4.57.1", + "@rollup/rollup-win32-ia32-msvc": "4.57.1", + "@rollup/rollup-win32-x64-gnu": "4.57.1", + "@rollup/rollup-win32-x64-msvc": "4.57.1", + "fsevents": "~2.3.2" + } + }, + "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/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "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/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.3", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/serve-static": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", + "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC", + "optional": true + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC", + "optional": true + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "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": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.7", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", + "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", + "license": "MIT", + "optional": true, + "dependencies": { + "ip-address": "^10.0.1", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", + "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "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==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sqlite3": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.7.tgz", + "integrity": "sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "bindings": "^1.5.0", + "node-addon-api": "^7.0.0", + "prebuild-install": "^7.1.1", + "tar": "^6.1.11" + }, + "optionalDependencies": { + "node-gyp": "8.x" + }, + "peerDependencies": { + "node-gyp": "8.x" + }, + "peerDependenciesMeta": { + "node-gyp": { + "optional": true + } + } + }, + "node_modules/ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": ">= 8" + } + }, + "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/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "optional": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "deprecated": "Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "license": "ISC" + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, + "node_modules/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/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==", + "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==", + "license": "ISC", + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "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/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "license": "MIT" + }, + "node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "license": "ISC", + "optional": true, + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vite": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", + "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.27.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "devOptional": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "license": "ISC", + "optional": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "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/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/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", + "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-validation-error": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", + "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 000000000..c98a40283 --- /dev/null +++ b/package.json @@ -0,0 +1,35 @@ +{ + "name": "she-wants", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "lint": "eslint .", + "preview": "vite preview", + "server": "node server/index.js", + "server:dev": "nodemon server/index.js" + }, + "dependencies": { + "axios": "^1.13.5", + "cors": "^2.8.6", + "dotenv": "^17.3.1", + "express": "^5.2.1", + "nodemon": "^3.1.11", + "react": "^19.2.0", + "react-dom": "^19.2.0", + "sqlite3": "^5.1.7" + }, + "devDependencies": { + "@eslint/js": "^9.39.1", + "@types/react": "^19.2.7", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^5.1.1", + "eslint": "^9.39.1", + "eslint-plugin-react-hooks": "^7.0.1", + "eslint-plugin-react-refresh": "^0.4.24", + "globals": "^16.5.0", + "vite": "^7.3.1" + } +} \ No newline at end of file diff --git a/period-tracker.html b/period-tracker.html new file mode 100644 index 000000000..380cf7840 --- /dev/null +++ b/period-tracker.html @@ -0,0 +1,32 @@ + + + + + + + Period Tracker - She Wants + + + + +

๐Ÿ“… Period Tracker

+

This feature is coming soon!

+

๐ŸŒธ

+ โ† Back to Dashboard + + + \ No newline at end of file diff --git a/public/vite.svg b/public/vite.svg new file mode 100644 index 000000000..e7b8dfb1b --- /dev/null +++ b/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/sample.html b/sample.html new file mode 100644 index 000000000..ff2fd40ff --- /dev/null +++ b/sample.html @@ -0,0 +1,1188 @@ + + + + + + + She Wants - Complete App + + + + + + +
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+
+ New User? +
+
+
+
+ + +
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+
๐ŸŒธ
+

Welcome Back!

+

Accessing Secure Dashboard...

+
+
+ + +
+
+
+

๐ŸŒธ She Wants

+
+ User + +
+
+ +
+
+ ๐Ÿ“… +

Period Tracker

+

Track your cycle

+
+
+ ๐Ÿ†˜ +

Emergency Support

+

Find nearby help

+
+
+ ๐Ÿ’ฌ +

Sisterhood Chat

+

Connect with others

+
+
+ +
+ +
+
+
+ + +
+
+

Emergency Support

+

Press to alert nearby helpers

+ + +
+
+ + +
+
+ + + + + + + + + + + + + She Wants - Complete App + + + + + + +
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+
+ New User? +
+
+
+
+ + +
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+
๐ŸŒธ
+

Welcome Back!

+

Accessing Secure Dashboard...

+
+
+ + +
+
+
+

๐ŸŒธ She Wants

+
+ User + +
+
+ +
+
+ ๐Ÿ“… +

Period Tracker

+

Track your cycle

+
+
+ ๐Ÿ†˜ +

Emergency Support

+

Find nearby help

+
+
+ ๐Ÿ’ฌ +

Sisterhood Chat

+

Connect with others

+
+
+ +
+ +
+
+
+ + +
+
+

Emergency Support

+

Press to alert nearby helpers

+ + +
+
+ + +
+
+ + + + + + \ No newline at end of file diff --git a/server/database.db b/server/database.db new file mode 100644 index 000000000..e69de29bb diff --git a/server/database.js b/server/database.js new file mode 100644 index 000000000..e45824250 --- /dev/null +++ b/server/database.js @@ -0,0 +1,111 @@ +import sqlite3 from 'sqlite3'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +const verboseSqlite = sqlite3.verbose(); +const dbPath = path.resolve(__dirname, 'shewants.db'); + +const db = new verboseSqlite.Database(dbPath, (err) => { + if (err) { + console.error('Error opening database:', err.message); + } else { + console.log('Connected to the SQLite database.'); + + // Create Users table + db.run(`CREATE TABLE IF NOT EXISTS users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + username TEXT UNIQUE NOT NULL, + password TEXT NOT NULL, + secret_code TEXT DEFAULT '1234=' + )`); + + // Create Cycles table (Period Tracker) + db.run(`CREATE TABLE IF NOT EXISTS cycles ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER NOT NULL, + start_date TEXT NOT NULL, + end_date TEXT, + FOREIGN KEY (user_id) REFERENCES users (id) + )`); + + // Create Emergency Contacts table + db.run(`CREATE TABLE IF NOT EXISTS emergency_contacts ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER NOT NULL, + name TEXT NOT NULL, + phone TEXT NOT NULL, + FOREIGN KEY (user_id) REFERENCES users (id) + )`); + + // Create Pad Requests table + db.run(`CREATE TABLE IF NOT EXISTS pad_requests ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER NOT NULL, + username TEXT NOT NULL, + latitude REAL NOT NULL, + longitude REAL NOT NULL, + status TEXT DEFAULT 'active', + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + fulfilled_by INTEGER, + FOREIGN KEY (user_id) REFERENCES users (id), + FOREIGN KEY (fulfilled_by) REFERENCES users (id) + )`); + + // Create Community Helpers table + db.run(`CREATE TABLE IF NOT EXISTS community_helpers ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER NOT NULL, + username TEXT NOT NULL, + bio TEXT, + available BOOLEAN DEFAULT 1, + latitude REAL, + longitude REAL, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (user_id) REFERENCES users (id), + UNIQUE(user_id) + )`); + + // Create Sisterhood Posts table + db.run(`CREATE TABLE IF NOT EXISTS sisterhood_posts ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER NOT NULL, + username TEXT NOT NULL, + category TEXT NOT NULL, + content TEXT NOT NULL, + is_anonymous BOOLEAN DEFAULT 0, + likes_count INTEGER DEFAULT 0, + comments_count INTEGER DEFAULT 0, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (user_id) REFERENCES users (id) + )`); + + // Create Post Comments table + db.run(`CREATE TABLE IF NOT EXISTS post_comments ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + post_id INTEGER NOT NULL, + user_id INTEGER NOT NULL, + username TEXT NOT NULL, + comment TEXT NOT NULL, + is_anonymous BOOLEAN DEFAULT 0, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (post_id) REFERENCES sisterhood_posts (id), + FOREIGN KEY (user_id) REFERENCES users (id) + )`); + + // Create Post Likes table + db.run(`CREATE TABLE IF NOT EXISTS post_likes ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + post_id INTEGER NOT NULL, + user_id INTEGER NOT NULL, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (post_id) REFERENCES sisterhood_posts (id), + FOREIGN KEY (user_id) REFERENCES users (id), + UNIQUE(post_id, user_id) + )`); + } +}); + +export default db; diff --git a/server/index.js b/server/index.js new file mode 100644 index 000000000..b7803c62c --- /dev/null +++ b/server/index.js @@ -0,0 +1,517 @@ +import express from 'express'; +import cors from 'cors'; +import db from './database.js'; // Note the .js extension for local imports in ESM +const app = express(); +const PORT = process.env.PORT || 3000; + +// CORS configuration for production +const allowedOrigins = [ + 'http://localhost:5173', + 'http://localhost:3000', + process.env.FRONTEND_URL, + 'https://she-wants.vercel.app' // Add your Vercel URL here +].filter(Boolean); + +app.use(cors({ + origin: function (origin, callback) { + // Allow requests with no origin (like mobile apps or curl) + if (!origin) return callback(null, true); + if (allowedOrigins.indexOf(origin) !== -1) { + callback(null, true); + } else { + console.log('Blocked origin:', origin); + callback(null, true); // Allow all for now, restrict in production + } + }, + credentials: true +})); + +app.use(express.json()); + +// --- Auth Routes --- + +// Register +app.post('/api/auth/register', (req, res) => { + const { username, password, secretCode } = req.body; + const code = secretCode || '1234='; // Default to 1234= if not provided + + // In a real app, hash password here! + const sql = 'INSERT INTO users (username, password, secret_code) VALUES (?, ?, ?)'; + db.run(sql, [username, password, code], function (err) { + if (err) { + return res.status(400).json({ error: err.message }); + } + res.json({ id: this.lastID, username, message: 'User created successfully' }); + }); +}); + +// Login +app.post('/api/auth/login', (req, res) => { + const { username, password } = req.body; + const sql = 'SELECT * FROM users WHERE username = ? AND password = ?'; + db.get(sql, [username, password], (err, row) => { + if (err) { + return res.status(500).json({ error: err.message }); + } + if (row) { + res.json({ message: 'Login successful', user: row }); + } else { + res.status(401).json({ message: 'Invalid credentials' }); + } + }); +}); + +// --- Feature Routes --- + +// Get Cycles with statistics +app.get('/api/cycles/:userId', (req, res) => { + const sql = 'SELECT * FROM cycles WHERE user_id = ? ORDER BY start_date DESC'; + db.all(sql, [req.params.userId], (err, rows) => { + if (err) { + return res.status(500).json({ error: err.message }); + } + + // Calculate cycle statistics + let avgCycleLength = null; + if (rows.length >= 2) { + let totalDays = 0; + for (let i = 0; i < rows.length - 1; i++) { + const current = new Date(rows[i].start_date); + const next = new Date(rows[i + 1].start_date); + totalDays += Math.abs((current - next) / (1000 * 60 * 60 * 24)); + } + avgCycleLength = Math.round(totalDays / (rows.length - 1)); + } + + res.json({ + cycles: rows, + statistics: { + totalCycles: rows.length, + averageCycleLength: avgCycleLength + } + }); + }); +}); + +// Add Cycle with validation +app.post('/api/cycles', (req, res) => { + const { userId, startDate } = req.body; + + if (!userId || !startDate) { + return res.status(400).json({ error: 'User ID and start date are required' }); + } + + // Check if cycle already exists for this date + const checkSql = 'SELECT * FROM cycles WHERE user_id = ? AND start_date = ?'; + db.get(checkSql, [userId, startDate], (err, existingCycle) => { + if (err) { + return res.status(500).json({ error: err.message }); + } + + if (existingCycle) { + return res.status(400).json({ error: 'Cycle already logged for this date' }); + } + + // Insert new cycle + const sql = 'INSERT INTO cycles (user_id, start_date) VALUES (?, ?)'; + db.run(sql, [userId, startDate], function (err) { + if (err) { + return res.status(500).json({ error: err.message }); + } + console.log(`Cycle logged for user ${userId} on ${startDate}`); + res.json({ + id: this.lastID, + message: 'Cycle logged successfully', + startDate: startDate + }); + }); + }); +}); + +// Delete a cycle +app.delete('/api/cycles/:cycleId', (req, res) => { + const { cycleId } = req.params; + const sql = 'DELETE FROM cycles WHERE id = ?'; + + db.run(sql, [cycleId], function (err) { + if (err) { + return res.status(500).json({ error: err.message }); + } + + if (this.changes === 0) { + return res.status(404).json({ error: 'Cycle not found' }); + } + + console.log(`Cycle ${cycleId} deleted`); + res.json({ message: 'Cycle deleted successfully' }); + }); +}); + +// --- Pad Request Routes --- + +// Create a pad request +app.post('/api/pad-request', (req, res) => { + const { userId, username, location } = req.body; + + if (!location || location.lat === 0 || !location.lng) { + return res.status(400).json({ error: 'Valid location is required for pad requests' }); + } + + const sql = 'INSERT INTO pad_requests (user_id, username, latitude, longitude, status) VALUES (?, ?, ?, ?, ?)'; + db.run(sql, [userId, username, location.lat, location.lng, 'active'], function (err) { + if (err) { + console.error('Error creating pad request:', err); + return res.status(500).json({ error: err.message }); + } + console.log(`Pad request created by ${username} (User ${userId}) at location: ${location.lat}, ${location.lng}`); + res.json({ + id: this.lastID, + message: 'Pad request sent! Nearby users will be notified.', + requestId: this.lastID + }); + }); +}); + +// Get nearby pad requests (active requests from other users) +app.get('/api/pad-requests/nearby/:userId', (req, res) => { + const userId = req.params.userId; + + // Get all active requests except from the current user + const sql = `SELECT id, user_id, username, latitude, longitude, created_at + FROM pad_requests + WHERE status = 'active' AND user_id != ? + ORDER BY created_at DESC`; + + db.all(sql, [userId], (err, rows) => { + if (err) { + console.error('Error fetching pad requests:', err); + return res.status(500).json({ error: err.message }); + } + res.json({ requests: rows }); + }); +}); + +// Get user's own pad requests +app.get('/api/pad-requests/my/:userId', (req, res) => { + const userId = req.params.userId; + + const sql = `SELECT id, latitude, longitude, status, created_at + FROM pad_requests + WHERE user_id = ? + ORDER BY created_at DESC`; + + db.all(sql, [userId], (err, rows) => { + if (err) { + console.error('Error fetching user pad requests:', err); + return res.status(500).json({ error: err.message }); + } + res.json({ requests: rows }); + }); +}); + +// Mark a pad request as fulfilled +app.post('/api/pad-request/fulfill', (req, res) => { + const { requestId, fulfilledBy } = req.body; + + const sql = 'UPDATE pad_requests SET status = ?, fulfilled_by = ? WHERE id = ?'; + db.run(sql, ['fulfilled', fulfilledBy, requestId], function (err) { + if (err) { + console.error('Error fulfilling pad request:', err); + return res.status(500).json({ error: err.message }); + } + console.log(`Pad request ${requestId} fulfilled by user ${fulfilledBy}`); + res.json({ message: 'Request marked as fulfilled!' }); + }); +}); + +// --- Community Helpers Routes --- + +// Register as a helper +app.post('/api/helpers/register', (req, res) => { + const { userId, username, bio, location } = req.body; + + const sql = `INSERT INTO community_helpers (user_id, username, bio, latitude, longitude, available) + VALUES (?, ?, ?, ?, ?, 1) + ON CONFLICT(user_id) DO UPDATE SET + bio = excluded.bio, + latitude = excluded.latitude, + longitude = excluded.longitude, + available = 1`; + + db.run(sql, [userId, username, bio || '', location?.lat || null, location?.lng || null], function (err) { + if (err) { + console.error('Error registering helper:', err); + return res.status(500).json({ error: err.message }); + } + console.log(`${username} (User ${userId}) registered as a community helper`); + res.json({ + message: 'Successfully registered as a helper!', + helperId: this.lastID + }); + }); +}); + +// Get all available helpers +app.get('/api/helpers', (req, res) => { + const sql = `SELECT id, user_id, username, bio, latitude, longitude, created_at + FROM community_helpers + WHERE available = 1 + ORDER BY created_at DESC`; + + db.all(sql, [], (err, rows) => { + if (err) { + console.error('Error fetching helpers:', err); + return res.status(500).json({ error: err.message }); + } + res.json({ helpers: rows }); + }); +}); + +// Check if user is a helper +app.get('/api/helpers/status/:userId', (req, res) => { + const { userId } = req.params; + + const sql = 'SELECT * FROM community_helpers WHERE user_id = ?'; + db.get(sql, [userId], (err, row) => { + if (err) { + console.error('Error checking helper status:', err); + return res.status(500).json({ error: err.message }); + } + res.json({ + isHelper: !!row, + helperData: row || null + }); + }); +}); + +// Update helper availability +app.put('/api/helpers/availability', (req, res) => { + const { userId, available } = req.body; + + const sql = 'UPDATE community_helpers SET available = ? WHERE user_id = ?'; + db.run(sql, [available ? 1 : 0, userId], function (err) { + if (err) { + console.error('Error updating availability:', err); + return res.status(500).json({ error: err.message }); + } + + if (this.changes === 0) { + return res.status(404).json({ error: 'Helper not found' }); + } + + console.log(`Helper ${userId} availability updated to ${available}`); + res.json({ message: 'Availability updated successfully' }); + }); +}); + +// Remove helper status +app.delete('/api/helpers/:userId', (req, res) => { + const { userId } = req.params; + + const sql = 'DELETE FROM community_helpers WHERE user_id = ?'; + db.run(sql, [userId], function (err) { + if (err) { + console.error('Error removing helper:', err); + return res.status(500).json({ error: err.message }); + } + + if (this.changes === 0) { + return res.status(404).json({ error: 'Helper not found' }); + } + + console.log(`User ${userId} removed from community helpers`); + res.json({ message: 'Helper status removed successfully' }); + }); +}); + +// --- Sisterhood Posts Routes --- + +// Get all posts or filter by category +app.get('/api/posts', (req, res) => { + const { category } = req.query; + + let sql = `SELECT * FROM sisterhood_posts`; + let params = []; + + if (category && category !== 'all') { + sql += ` WHERE category = ?`; + params.push(category); + } + + sql += ` ORDER BY created_at DESC`; + + db.all(sql, params, (err, rows) => { + if (err) { + console.error('Error fetching posts:', err); + return res.status(500).json({ error: err.message }); + } + res.json({ posts: rows }); + }); +}); + +// Create a new post +app.post('/api/posts', (req, res) => { + const { userId, username, category, content, isAnonymous } = req.body; + + if (!content || !category) { + return res.status(400).json({ error: 'Content and category are required' }); + } + + const displayName = isAnonymous ? 'Anonymous' : username; + + const sql = `INSERT INTO sisterhood_posts (user_id, username, category, content, is_anonymous) + VALUES (?, ?, ?, ?, ?)`; + + db.run(sql, [userId, displayName, category, content, isAnonymous ? 1 : 0], function (err) { + if (err) { + console.error('Error creating post:', err); + return res.status(500).json({ error: err.message }); + } + console.log(`Post created by ${displayName} in category ${category}`); + res.json({ + id: this.lastID, + message: 'Post created successfully' + }); + }); +}); + +// Get a single post with comments +app.get('/api/posts/:postId', (req, res) => { + const { postId } = req.params; + + const postSql = 'SELECT * FROM sisterhood_posts WHERE id = ?'; + const commentsSql = 'SELECT * FROM post_comments WHERE post_id = ? ORDER BY created_at ASC'; + + db.get(postSql, [postId], (err, post) => { + if (err) { + console.error('Error fetching post:', err); + return res.status(500).json({ error: err.message }); + } + + if (!post) { + return res.status(404).json({ error: 'Post not found' }); + } + + db.all(commentsSql, [postId], (err, comments) => { + if (err) { + console.error('Error fetching comments:', err); + return res.status(500).json({ error: err.message }); + } + + res.json({ + post: post, + comments: comments + }); + }); + }); +}); + +// Like/Unlike a post +app.post('/api/posts/:postId/like', (req, res) => { + const { postId } = req.params; + const { userId } = req.body; + + // Check if already liked + const checkSql = 'SELECT * FROM post_likes WHERE post_id = ? AND user_id = ?'; + db.get(checkSql, [postId, userId], (err, like) => { + if (err) { + console.error('Error checking like:', err); + return res.status(500).json({ error: err.message }); + } + + if (like) { + // Unlike + const deleteSql = 'DELETE FROM post_likes WHERE post_id = ? AND user_id = ?'; + const updateSql = 'UPDATE sisterhood_posts SET likes_count = likes_count - 1 WHERE id = ?'; + + db.run(deleteSql, [postId, userId], (err) => { + if (err) { + console.error('Error unliking post:', err); + return res.status(500).json({ error: err.message }); + } + + db.run(updateSql, [postId], (err) => { + if (err) { + console.error('Error updating likes count:', err); + return res.status(500).json({ error: err.message }); + } + res.json({ liked: false, message: 'Post unliked' }); + }); + }); + } else { + // Like + const insertSql = 'INSERT INTO post_likes (post_id, user_id) VALUES (?, ?)'; + const updateSql = 'UPDATE sisterhood_posts SET likes_count = likes_count + 1 WHERE id = ?'; + + db.run(insertSql, [postId, userId], (err) => { + if (err) { + console.error('Error liking post:', err); + return res.status(500).json({ error: err.message }); + } + + db.run(updateSql, [postId], (err) => { + if (err) { + console.error('Error updating likes count:', err); + return res.status(500).json({ error: err.message }); + } + res.json({ liked: true, message: 'Post liked' }); + }); + }); + } + }); +}); + +// Add a comment to a post +app.post('/api/posts/:postId/comment', (req, res) => { + const { postId } = req.params; + const { userId, username, comment, isAnonymous } = req.body; + + if (!comment) { + return res.status(400).json({ error: 'Comment is required' }); + } + + const displayName = isAnonymous ? 'Anonymous' : username; + + const insertSql = `INSERT INTO post_comments (post_id, user_id, username, comment, is_anonymous) + VALUES (?, ?, ?, ?, ?)`; + const updateSql = 'UPDATE sisterhood_posts SET comments_count = comments_count + 1 WHERE id = ?'; + + db.run(insertSql, [postId, userId, displayName, comment, isAnonymous ? 1 : 0], function (err) { + if (err) { + console.error('Error adding comment:', err); + return res.status(500).json({ error: err.message }); + } + + db.run(updateSql, [postId], (err) => { + if (err) { + console.error('Error updating comments count:', err); + return res.status(500).json({ error: err.message }); + } + + console.log(`Comment added to post ${postId} by ${displayName}`); + res.json({ + id: this.lastID, + message: 'Comment added successfully' + }); + }); + }); +}); + +// Check if user liked a post +app.get('/api/posts/:postId/liked/:userId', (req, res) => { + const { postId, userId } = req.params; + + const sql = 'SELECT * FROM post_likes WHERE post_id = ? AND user_id = ?'; + db.get(sql, [postId, userId], (err, like) => { + if (err) { + console.error('Error checking like status:', err); + return res.status(500).json({ error: err.message }); + } + res.json({ liked: !!like }); + }); +}); + + +app.listen(PORT, () => { + console.log(`Server running on http://localhost:${PORT}`); +}); diff --git a/server/shewants.db b/server/shewants.db new file mode 100644 index 000000000..59713a46f Binary files /dev/null and b/server/shewants.db differ diff --git a/she_wants_full_app.html b/she_wants_full_app.html new file mode 100644 index 000000000..c72942efa --- /dev/null +++ b/she_wants_full_app.html @@ -0,0 +1,594 @@ + + + + + + + She Wants - Complete App + + + + + + +
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+
+ New User? +
+
+
+
+ + +
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+
๐ŸŒธ
+

Welcome Back!

+

Accessing Secure Dashboard...

+
+
+ + +
+
+
+

๐ŸŒธ She Wants

+
+ User + +
+
+ +
+
+ ๐Ÿ“… +

Period Tracker

+

Track your cycle

+
+
+ ๐Ÿ†˜ +

Emergency Support

+

Find nearby help

+
+
+ ๐Ÿ’ฌ +

Sisterhood Chat

+

Connect with others

+
+
+ +
+ +
+
+
+ + +
+
+

Emergency Support

+

Press to alert nearby helpers

+ + +
+
+ + +
+
+ + + + + + \ No newline at end of file diff --git a/signup.html b/signup.html new file mode 100644 index 000000000..05a8ac73b --- /dev/null +++ b/signup.html @@ -0,0 +1,561 @@ + + + + + + + She Wants - Sign Up + + + + + + + + + + + + \ No newline at end of file diff --git a/src/App.css b/src/App.css new file mode 100644 index 000000000..b9d355df2 --- /dev/null +++ b/src/App.css @@ -0,0 +1,42 @@ +#root { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + +.logo { + height: 6em; + padding: 1.5em; + will-change: filter; + transition: filter 300ms; +} +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); +} +.logo.react:hover { + filter: drop-shadow(0 0 2em #61dafbaa); +} + +@keyframes logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +@media (prefers-reduced-motion: no-preference) { + a:nth-of-type(2) .logo { + animation: logo-spin infinite 20s linear; + } +} + +.card { + padding: 2em; +} + +.read-the-docs { + color: #888; +} diff --git a/src/App.jsx b/src/App.jsx new file mode 100644 index 000000000..5d9c7ca15 --- /dev/null +++ b/src/App.jsx @@ -0,0 +1,50 @@ +import React, { useState } from 'react'; +import Calculator from './components/Calculator'; +import Auth from './components/Auth'; +import Dashboard from './components/Dashboard'; +import './index.css'; + +function App() { + const [isLocked, setIsLocked] = useState(true); // Start locked (showing calculator) + const [user, setUser] = useState(null); + + const handleUnlock = (enteredCode) => { + // Secret code to access the auth screen (1234=) + if (enteredCode === '1234=') { + setIsLocked(false); + return true; + } + + // If user is logged in, verify their personal secret code + if (user && user.secret_code === enteredCode) { + setIsLocked(false); + return true; + } + + return false; + }; + + const handleLogin = (userData) => { + setUser(userData); + setIsLocked(false); // Unlock after successful login + }; + + const handleLogout = () => { + setUser(null); + setIsLocked(true); // Lock to show calculator after logout + }; + + return ( +
+ {isLocked ? ( + + ) : !user ? ( + + ) : ( + + )} +
+ ); +} + +export default App; diff --git a/src/assets/react.svg b/src/assets/react.svg new file mode 100644 index 000000000..6c87de9bb --- /dev/null +++ b/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/Auth.jsx b/src/components/Auth.jsx new file mode 100644 index 000000000..a754054a2 --- /dev/null +++ b/src/components/Auth.jsx @@ -0,0 +1,123 @@ +import React, { useState } from 'react'; +import axios from '../config/api'; + +const Auth = ({ onLogin }) => { + const [isLogin, setIsLogin] = useState(true); + const [username, setUsername] = useState(''); + const [password, setPassword] = useState(''); + const [secretCode, setSecretCode] = useState(''); + const [error, setError] = useState(''); + const [success, setSuccess] = useState(''); + + const handleSubmit = async (e) => { + e.preventDefault(); + setError(''); + setSuccess(''); + + // Validation for registration + if (!isLogin) { + if (!secretCode || secretCode.length < 4) { + setError('Secret code must be at least 4 characters'); + return; + } + if (secretCode.includes('=')) { + setError('Secret code cannot contain "=" symbol'); + return; + } + } + + const endpoint = isLogin ? '/api/auth/login' : '/api/auth/register'; + const payload = isLogin + ? { username, password } + : { username, password, secretCode: secretCode + '=' }; + + try { + const res = await axios.post(endpoint, payload); + if (isLogin) { + onLogin(res.data.user); + } else { + setSuccess('Registration successful! Please login with your credentials.'); + setIsLogin(true); + setUsername(''); + setPassword(''); + setSecretCode(''); + } + } catch (err) { + setError(err.response?.data?.error || err.response?.data?.message || 'An error occurred'); + } + }; + + return ( +
+
+

{isLogin ? '๐Ÿ”’ Welcome Back' : '๐ŸŒธ Join SheWants'}

+

+ {isLogin ? 'Enter your credentials to access your safe space' : 'Create your secure account'} +

+
+ +
+
+ + setUsername(e.target.value)} + required + /> +
+ +
+ + setPassword(e.target.value)} + required + /> +
+ + {!isLogin && ( +
+ + setSecretCode(e.target.value)} + required + maxLength="10" + /> + + This code will unlock the calculator. Enter it followed by "=" on the calculator. + +
+ )} + + +
+ + {error &&
โŒ {error}
} + {success &&
โœ… {success}
} + +
+

{ + setIsLogin(!isLogin); + setError(''); + setSuccess(''); + setUsername(''); + setPassword(''); + setSecretCode(''); + }}> + {isLogin ? "Don't have an account? Sign up" : 'Already have an account? Login'} +

+
+
+ ); +}; + +export default Auth; diff --git a/src/components/Calculator.css b/src/components/Calculator.css new file mode 100644 index 000000000..1c149e814 --- /dev/null +++ b/src/components/Calculator.css @@ -0,0 +1,2 @@ +/* Calculator specific styles are in index.css */ +/* This file exists to satisfy the import in Calculator.jsx */ \ No newline at end of file diff --git a/src/components/Calculator.jsx b/src/components/Calculator.jsx new file mode 100644 index 000000000..2569df658 --- /dev/null +++ b/src/components/Calculator.jsx @@ -0,0 +1,107 @@ +import React, { useState } from 'react'; +import './Calculator.css'; + +const Calculator = ({ onUnlock, user }) => { + const [display, setDisplay] = useState(''); + const [error, setError] = useState(''); + + const handlePress = (val) => { + if (val === '=') { + try { + const enteredCode = display + '='; + + // If user is logged in, check their specific code + if (user) { + if (user.secret_code === enteredCode) { + onUnlock(enteredCode); + setDisplay(''); + setError(''); + } else { + setError('Wrong code!'); + setDisplay(''); + setTimeout(() => setError(''), 2000); + } + } else { + // No user logged in, use default code or just unlock + if (enteredCode === '1234=') { + onUnlock(enteredCode); + setDisplay(''); + setError(''); + } else { + // Try to evaluate as math + setDisplay(eval(display).toString()); + } + } + } catch (e) { + setDisplay('Error'); + setTimeout(() => setDisplay(''), 1000); + } + } else if (val === 'C') { + setDisplay(''); + setError(''); + } else { + setDisplay(display + val); + } + }; + + const buttons = [ + '7', '8', '9', '/', + '4', '5', '6', '*', + '1', '2', '3', '-', + 'C', '0', '=', '+' + ]; + + return ( +
+
{display || (error ? error : '0')}
+
+ {buttons.map((btn) => ( + + ))} +
+ {user ? ( +

+ Welcome back, {user.username}! Enter your secret code. +

+ ) : ( +
+

+ Not signed in yet? +

+ +

+ ๐Ÿ’ก Hint: Or enter 1234= on the calculator +

+
+ )} +
+ ); +}; + +export default Calculator; diff --git a/src/components/CommunitySupport.jsx b/src/components/CommunitySupport.jsx new file mode 100644 index 000000000..201d1e5b8 --- /dev/null +++ b/src/components/CommunitySupport.jsx @@ -0,0 +1,315 @@ +import React, { useState, useEffect } from 'react'; +import axios from '../config/api'; + +const CommunitySupport = ({ user }) => { + const [helpers, setHelpers] = useState([]); + const [isHelper, setIsHelper] = useState(false); + const [helperData, setHelperData] = useState(null); + const [loading, setLoading] = useState(true); + const [showRegisterForm, setShowRegisterForm] = useState(false); + const [bio, setBio] = useState(''); + const [registering, setRegistering] = useState(false); + + useEffect(() => { + fetchHelperStatus(); + fetchHelpers(); + }, []); + + const fetchHelperStatus = async () => { + try { + const res = await axios.get(`/api/helpers/status/${user.id}`); + setIsHelper(res.data.isHelper); + setHelperData(res.data.helperData); + if (res.data.helperData) { + setBio(res.data.helperData.bio || ''); + } + } catch (err) { + console.error('Error fetching helper status:', err); + } + }; + + const fetchHelpers = async () => { + try { + const res = await axios.get('/api/helpers'); + // Filter out current user from helpers list + const filteredHelpers = res.data.helpers.filter(h => h.user_id !== user.id); + setHelpers(filteredHelpers); + } catch (err) { + console.error('Error fetching helpers:', err); + } finally { + setLoading(false); + } + }; + + const handleRegisterAsHelper = async () => { + setRegistering(true); + + // Try to get location + if (navigator.geolocation) { + navigator.geolocation.getCurrentPosition( + async (position) => { + const location = { + lat: position.coords.latitude, + lng: position.coords.longitude + }; + await registerHelper(location); + }, + async (error) => { + console.log('Location not available, registering without location'); + await registerHelper(null); + } + ); + } else { + await registerHelper(null); + } + }; + + const registerHelper = async (location) => { + try { + await axios.post('/api/helpers/register', { + userId: user.id, + username: user.username, + bio: bio, + location: location + }); + alert('โœ… You are now a community helper!'); + setShowRegisterForm(false); + await fetchHelperStatus(); + await fetchHelpers(); + } catch (err) { + console.error('Error registering as helper:', err); + alert('Failed to register. Please try again.'); + } finally { + setRegistering(false); + } + }; + + const handleToggleAvailability = async () => { + try { + const newAvailability = !helperData.available; + await axios.put('/api/helpers/availability', { + userId: user.id, + available: newAvailability + }); + alert(`Availability updated to ${newAvailability ? 'Available' : 'Unavailable'}`); + await fetchHelperStatus(); + await fetchHelpers(); + } catch (err) { + console.error('Error updating availability:', err); + alert('Failed to update availability.'); + } + }; + + const handleRemoveHelper = async () => { + if (!window.confirm('Are you sure you want to remove yourself as a helper?')) { + return; + } + + try { + await axios.delete(`/api/helpers/${user.id}`); + alert('You have been removed as a helper.'); + await fetchHelperStatus(); + await fetchHelpers(); + } catch (err) { + console.error('Error removing helper:', err); + alert('Failed to remove helper status.'); + } + }; + + return ( +
+

๐Ÿ’ Community Support

+

+ Connect with verified helpers in your community who can provide support. +

+ + {/* Helper Status Section */} + {isHelper ? ( +
+
+
+

+ โœจ You are a Helper +

+

+ Status: {helperData?.available ? '๐ŸŸข Available' : '๐Ÿ”ด Unavailable'} +

+
+ +
+ {helperData?.bio && ( +

+ "{helperData.bio}" +

+ )} + +
+ ) : showRegisterForm ? ( +
+

Become a Helper

+