diff --git a/README.md b/README.md
deleted file mode 100644
index e49d643a..00000000
--- a/README.md
+++ /dev/null
@@ -1,34 +0,0 @@
-# webSDK-sample
-Sample WebSDK integration
-
-[Basic Integration](index.html)
-
-[Integration with Debugging enabled](debug.html)
-
-[Self Handled Opt-in Sample](self-handled-push.html)
-
-[Custom Service Worker](custom-serviceworker.html)
-
-[Web Personalization](web-personalization.html)
-
-[Angular App Sample Code](angular-sample/)
-
-[React App Sample Code](react-sample/)
-
-[Nuxt JS SPA](nuxt-spa/)
-
-[Next JS](nextjs/)
-
-[Google Tag Manager](google-tag-manager/)
-
-[LG Web OS](lg-web-os/)
-
-[Samsung Tizen OS](samsung-tizen-os/samsungTizenOs/)
-
-[PWA](pwa/)
-
-[npm](npm/)
-
-[Chrome Extension](chrome-extension/)
-
-[Magento](magento/)
diff --git a/chatgpt-app-sample/.eslintrc.json b/chatgpt-app-sample/.eslintrc.json
new file mode 100644
index 00000000..f18272b8
--- /dev/null
+++ b/chatgpt-app-sample/.eslintrc.json
@@ -0,0 +1,4 @@
+{
+ "extends": "next/core-web-vitals"
+}
+
diff --git a/chatgpt-app-sample/.gitignore b/chatgpt-app-sample/.gitignore
new file mode 100644
index 00000000..bbf87739
--- /dev/null
+++ b/chatgpt-app-sample/.gitignore
@@ -0,0 +1,30 @@
+# Dependencies
+node_modules/
+
+# Next.js
+.next/
+out/
+.vercel
+
+# Environment variables
+.env*.local
+.env
+
+# Debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# OS
+.DS_Store
+Thumbs.db
+
+# IDE
+.vscode/
+.idea/
+*.swp
+*.swo
+
+# Build
+dist/
+build/
diff --git a/chatgpt-app-sample/CHATGPT_DIRECT_USE.md b/chatgpt-app-sample/CHATGPT_DIRECT_USE.md
new file mode 100644
index 00000000..11056cfc
--- /dev/null
+++ b/chatgpt-app-sample/CHATGPT_DIRECT_USE.md
@@ -0,0 +1,342 @@
+# 🚀 Use Your App Directly in ChatGPT - Step by Step
+
+This guide will help you deploy and use your hotel booking app directly in ChatGPT in just a few minutes.
+
+---
+
+## Step 1: Deploy to Vercel (5 minutes)
+
+### Option A: Deploy from GitHub (Easiest)
+
+1. **Go to Vercel Dashboard**:
+ - Visit: https://vercel.com/new
+ - Click **"Import Git Repository"**
+
+2. **Select Your Repository**:
+ - Find: `moengage/webSDK-sample`
+ - Branch: `feat/chatgpt-app-integration`
+ - Click **"Import"**
+
+3. **Configure Project**:
+ - Framework: **Next.js** (auto-detected)
+ - Root Directory: **`chatgpt-app-sample`** ⚠️ **IMPORTANT**
+ - Build Command: `npm run build` (default)
+ - Output Directory: `.next` (default)
+
+4. **Add Environment Variables**:
+ Click **"Environment Variables"** and add:
+
+ **Variable 1:**
+ - Name: `NEXT_PUBLIC_MOENGAGE_DATACENTER`
+ - Value: `dc_01`
+ - Click **"Add"**
+
+ **Variable 2:**
+ - Name: `NEXT_PUBLIC_MOENGAGE_APP_ID`
+ - Value: `3RADPYNEBZ2MCOJ43EEW5FWV`
+ - Click **"Add"**
+
+5. **Deploy**:
+ - Click **"Deploy"** button
+ - Wait 2-3 minutes for deployment
+ - **Copy your deployment URL** (e.g., `https://websdk-sample-xyz.vercel.app`)
+
+### Option B: Deploy via CLI
+
+```bash
+cd /Users/aman.verma/Desktop/Projects/OPEN_AI_SDK/chatgpt-app-sample
+
+# Login to Vercel
+vercel login
+
+# Deploy
+vercel
+
+# When prompted:
+# - Link to existing? → N
+# - Project name → Press Enter
+# - Directory → Type: chatgpt-app-sample
+# - Override? → N
+```
+
+Then add environment variables in Vercel dashboard.
+
+---
+
+## Step 2: Update Configuration Files
+
+After deployment, you need to update the config files with your **actual Vercel URL**.
+
+### 2.1 Update `public/ai-plugin.json`
+
+Replace `https://your-app.vercel.app` with your actual URL:
+
+```json
+{
+ "api": {
+ "url": "https://YOUR-ACTUAL-URL.vercel.app/.well-known/openapi.yaml"
+ },
+ "logo_url": "https://YOUR-ACTUAL-URL.vercel.app/logo.png",
+ "legal_info_url": "https://YOUR-ACTUAL-URL.vercel.app/legal"
+}
+```
+
+### 2.2 Update `public/.well-known/openapi.yaml`
+
+Replace `https://your-app.vercel.app` with your actual URL:
+
+```yaml
+servers:
+ - url: https://YOUR-ACTUAL-URL.vercel.app
+```
+
+### 2.3 Commit and Push
+
+```bash
+cd /Users/aman.verma/Desktop/Projects/OPEN_AI_SDK/chatgpt-app-sample
+
+git add public/ai-plugin.json public/.well-known/openapi.yaml
+git commit -m "Update deployment URLs"
+git push origin feat/chatgpt-app-integration
+```
+
+Vercel will automatically redeploy!
+
+---
+
+## Step 3: Create ChatGPT GPT (2 minutes)
+
+1. **Go to OpenAI Platform**:
+ - Visit: https://platform.openai.com/
+ - Make sure you're logged in with **ChatGPT Plus** account
+
+2. **Create New GPT**:
+ - Click **"GPTs"** in left sidebar
+ - Click **"Create"** or **"+"** button
+
+3. **Configure Your GPT**:
+
+ **In the "Configure" tab:**
+
+ - **Name**: `Hotel Booking Assistant`
+ - **Description**: `Search and book hotels with real-time availability`
+ - **Instructions**:
+ ```
+ You are a helpful hotel booking assistant. When users ask about hotels,
+ help them search for available hotels by destination, dates, and number of guests.
+ Use the hotel booking widget to show them options and help them complete bookings.
+ ```
+
+4. **Add Widget** (This is the key step!):
+
+ - Scroll down to find **"Widget"** section (or look for "Additional Settings")
+ - **Widget URL**: Enter your Vercel URL
+ ```
+ https://YOUR-ACTUAL-URL.vercel.app
+ ```
+
+ - **Widget CSP** (Content Security Policy) - Click to expand and add:
+ ```json
+ {
+ "openai/widgetCSP": {
+ "connect_domains": [
+ "https://*.moengage.com",
+ "https://api.moengage.com"
+ ],
+ "resource_domains": [
+ "https://js.moengage.com",
+ "https://cdn.moengage.com",
+ "https://sdk-0X-moengage.com"
+ ]
+ }
+ }
+ ```
+
+5. **Save Your GPT**:
+ - Click **"Save"** button (top right)
+ - Choose visibility:
+ - **"Only me"** - For testing
+ - **"Anyone with a link"** - To share with others
+ - **"Public"** - Make it public
+ - Click **"Confirm"**
+
+---
+
+## Step 4: Use in ChatGPT (1 minute)
+
+1. **Open ChatGPT**:
+ - Go to: https://chat.openai.com
+ - Make sure you're logged in
+
+2. **Access Your GPT**:
+ - Click on your **profile/name** (top right corner)
+ - Click **"My GPTs"**
+ - Find and click **"Hotel Booking Assistant"**
+
+3. **Start Using It!**
+
+ Try these commands:
+
+ ```
+ "I want to book a hotel in Paris for next week"
+ ```
+
+ ```
+ "Find hotels in New York from December 20 to December 25 for 2 guests"
+ ```
+
+ ```
+ "Show me hotels in Tokyo"
+ ```
+
+4. **The Widget Will Appear!**
+ - Your hotel booking app will load inside ChatGPT
+ - You can search, view hotels, and complete bookings
+ - All actions are tracked in MoEngage!
+
+---
+
+## Step 5: Verify Everything Works
+
+### Check Widget Loading:
+1. Open **Browser DevTools** (Press `F12`)
+2. Go to **"Console"** tab
+3. Look for any errors (should be none)
+4. Check **"Network"** tab → Filter `moengage`
+5. You should see SDK loading requests
+
+### Check MoEngage Tracking:
+1. Perform actions in the app:
+ - Search for hotels
+ - View hotel details
+ - Start booking
+ - Complete booking
+
+2. Check MoEngage Dashboard:
+ - Go to: https://app.moengage.com/
+ - Login to your account
+ - Go to **"Analytics"** → **"Events"**
+ - Look for events:
+ - `app_loaded`
+ - `hotel_search`
+ - `hotel_viewed`
+ - `booking_started`
+ - `booking_completed`
+ - `gpt_app_session_start` ✅ (This confirms it's running in ChatGPT!)
+
+3. Check User Attributes:
+ - Go to **"Users"** section
+ - Look for:
+ - `gpt_app_user: true` ✅
+ - `ai_platform: "chatgpt"` ✅
+ - `is_gpt_app: true` ✅
+
+---
+
+## 🎯 Quick Reference
+
+### Your Deployment URL Format:
+```
+https://websdk-sample-[random].vercel.app
+```
+
+### Widget URL in ChatGPT:
+```
+https://YOUR-VERCEL-URL.vercel.app
+```
+
+### Environment Variables:
+```
+NEXT_PUBLIC_MOENGAGE_DATACENTER=dc_01
+NEXT_PUBLIC_MOENGAGE_APP_ID=3RADPYNEBZ2MCOJ43EEW5FWV
+```
+
+---
+
+## 🐛 Troubleshooting
+
+### Widget Not Showing?
+
+1. **Check Widget URL**:
+ - Make sure it's exactly: `https://YOUR-URL.vercel.app`
+ - No trailing slash
+ - Must be HTTPS
+
+2. **Check Browser Console**:
+ - Press `F12` → Console tab
+ - Look for errors
+ - Common issues:
+ - CSP errors → Check Widget CSP settings
+ - CORS errors → Already handled in code
+ - 404 errors → Check URL is correct
+
+3. **Check Vercel Deployment**:
+ - Go to Vercel dashboard
+ - Check deployment status (should be "Ready")
+ - Check build logs for errors
+
+### MoEngage Not Tracking?
+
+1. **Check SDK Loading**:
+ - DevTools → Network tab
+ - Filter: `moengage`
+ - Look for `sdk.js` file loading
+ - Should see 200 status
+
+2. **Check Environment Variables**:
+ - Vercel Dashboard → Settings → Environment Variables
+ - Make sure both are set correctly
+ - Redeploy after adding
+
+3. **Check App ID**:
+ - Verify `NEXT_PUBLIC_MOENGAGE_APP_ID` is correct
+ - Check MoEngage dashboard for correct App ID
+
+### Events Not Appearing?
+
+1. **Wait 1-2 minutes** - Events may be delayed
+2. **Check Dashboard Filters** - Make sure no date filters
+3. **Check Correct App** - Verify you're looking at right MoEngage app
+4. **Check Debug Logs** - Enable in `.env.local`:
+ ```
+ NEXT_PUBLIC_MOENGAGE_DEBUG_LOGS=1
+ ```
+
+---
+
+## ✅ Success Checklist
+
+- [ ] App deployed to Vercel
+- [ ] Environment variables added
+- [ ] Config files updated with Vercel URL
+- [ ] ChatGPT GPT created
+- [ ] Widget URL added
+- [ ] Widget CSP configured
+- [ ] GPT saved
+- [ ] Widget appears in ChatGPT
+- [ ] MoEngage SDK loads
+- [ ] Events tracking in dashboard
+- [ ] User attributes set correctly
+
+---
+
+## 🎉 You're Done!
+
+Once you complete these steps, your hotel booking app will work directly in ChatGPT!
+
+**Test it now:**
+1. Open ChatGPT
+2. Go to "My GPTs"
+3. Select "Hotel Booking Assistant"
+4. Try: `"I want to book a hotel in Paris"`
+
+The widget will appear and you can start booking hotels! 🚀
+
+---
+
+## 📞 Need Help?
+
+- **Vercel Issues**: https://vercel.com/docs
+- **ChatGPT GPTs**: https://platform.openai.com/docs/guides/gpts
+- **MoEngage Docs**: https://docs.moengage.com/
+
diff --git a/chatgpt-app-sample/CHATGPT_TESTING_GUIDE.md b/chatgpt-app-sample/CHATGPT_TESTING_GUIDE.md
new file mode 100644
index 00000000..5a3fc83e
--- /dev/null
+++ b/chatgpt-app-sample/CHATGPT_TESTING_GUIDE.md
@@ -0,0 +1,431 @@
+# Complete Guide: Testing Your Booking.com App in ChatGPT
+
+This guide will walk you through every step to test your MoEngage-integrated hotel booking app inside ChatGPT.
+
+## Prerequisites
+
+1. **OpenAI Account**: You need a ChatGPT Plus subscription (required for GPT apps)
+2. **Deployed App**: Your app must be deployed and accessible via HTTPS
+3. **MoEngage Account**: Access to MoEngage dashboard to verify events
+
+---
+
+## Step 1: Deploy Your App
+
+### Option A: Deploy to Vercel (Recommended)
+
+1. **Install Vercel CLI** (if not already installed):
+ ```bash
+ npm install -g vercel
+ ```
+
+2. **Deploy from your project directory**:
+ ```bash
+ cd /Users/aman.verma/Desktop/Projects/OPEN_AI_SDK/chatgpt-app-sample
+ vercel
+ ```
+
+3. **Follow the prompts**:
+ - Link to existing project or create new
+ - Confirm project settings
+ - Wait for deployment to complete
+
+4. **Note your deployment URL**: You'll get a URL like `https://your-app.vercel.app`
+
+### Option B: Deploy to Other Platforms
+
+- **Netlify**: `npm run build` then drag `out` folder to Netlify
+- **Railway**: Connect GitHub repo and deploy
+- **Any HTTPS hosting**: Ensure your app is accessible via HTTPS
+
+---
+
+## Step 2: Configure Environment Variables
+
+1. **Create `.env.local` file** (if not exists):
+ ```bash
+ NEXT_PUBLIC_MOENGAGE_DATACENTER=dc_01
+ NEXT_PUBLIC_MOENGAGE_APP_ID=3RADPYNEBZ2MCOJ43EEW5FWV
+ ```
+
+2. **Redeploy** after adding environment variables:
+ ```bash
+ vercel --prod
+ ```
+
+---
+
+## Step 3: Create ChatGPT App Configuration
+
+### 3.1 Create `ai-plugin.json` File
+
+Create a file named `ai-plugin.json` in your `public` folder:
+
+```json
+{
+ "schema_version": "v1",
+ "name_for_human": "Hotel Booking",
+ "name_for_model": "hotel_booking",
+ "description_for_human": "Search and book hotels with real-time availability and pricing.",
+ "description_for_model": "A hotel booking service that allows users to search for hotels by destination, check-in/check-out dates, and number of guests. Users can view hotel details, compare prices, and complete bookings.",
+ "auth": {
+ "type": "none"
+ },
+ "api": {
+ "type": "openapi",
+ "url": "https://your-app.vercel.app/.well-known/openapi.yaml"
+ },
+ "logo_url": "https://your-app.vercel.app/logo.png",
+ "contact_email": "support@example.com",
+ "legal_info_url": "https://your-app.vercel.app/legal"
+}
+```
+
+### 3.2 Create OpenAPI Specification
+
+Create `public/.well-known/openapi.yaml`:
+
+```yaml
+openapi: 3.0.0
+info:
+ title: Hotel Booking API
+ version: 1.0.0
+ description: API for searching and booking hotels
+servers:
+ - url: https://your-app.vercel.app
+paths:
+ /:
+ get:
+ summary: Hotel booking interface
+ description: Main interface for hotel search and booking
+ responses:
+ '200':
+ description: HTML page with hotel booking interface
+```
+
+### 3.3 Update Next.js Config for ChatGPT Apps
+
+Update `next.config.js`:
+
+```javascript
+/** @type {import('next').NextConfig} */
+const nextConfig = {
+ reactStrictMode: true,
+ swcMinify: true,
+ async headers() {
+ return [
+ {
+ source: '/.well-known/:path*',
+ headers: [
+ {
+ key: 'Access-Control-Allow-Origin',
+ value: '*',
+ },
+ {
+ key: 'Content-Type',
+ value: 'application/json',
+ },
+ ],
+ },
+ {
+ source: '/:path*',
+ headers: [
+ {
+ key: 'X-Frame-Options',
+ value: 'ALLOWALL',
+ },
+ {
+ key: 'Content-Security-Policy',
+ value: "frame-ancestors 'self' https://chat.openai.com https://chatgpt.com;",
+ },
+ ],
+ },
+ ];
+ },
+};
+
+module.exports = nextConfig;
+```
+
+---
+
+## Step 4: Configure Content Security Policy for MoEngage
+
+### 4.1 Update `app/layout.tsx`
+
+Add CSP meta tag to allow MoEngage SDK:
+
+```tsx
+export default function RootLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return (
+
+
+
+
+
+ {children}
+
+ );
+}
+```
+
+---
+
+## Step 5: Create ChatGPT App in OpenAI Platform
+
+1. **Go to OpenAI Platform**: https://platform.openai.com/
+
+2. **Navigate to GPTs**: Click on "GPTs" in the left sidebar
+
+3. **Create New GPT**:
+ - Click "Create" or "+" button
+ - Choose "Create a GPT"
+
+4. **Configure Your GPT**:
+ - **Name**: "Hotel Booking Assistant"
+ - **Description**: "Helps users search and book hotels"
+ - **Instructions**:
+ ```
+ You are a helpful hotel booking assistant. When users ask about hotels,
+ use the hotel booking tool to search for available hotels. Help them
+ find the best options based on their destination, dates, and preferences.
+ ```
+
+5. **Add Action/Plugin**:
+ - Click "Add Action" or "Configure"
+ - **Authentication**: Select "No Auth" (for testing)
+ - **Schema**: Paste your OpenAPI schema or upload `openapi.yaml`
+
+6. **Configure Widget**:
+ - In the GPT configuration, go to "Widget" section
+ - **Widget URL**: `https://your-app.vercel.app`
+ - **Widget CSP**: Add the following:
+ ```json
+ {
+ "openai/widgetCSP": {
+ "connect_domains": [
+ "https://*.moengage.com",
+ "https://api.moengage.com"
+ ],
+ "resource_domains": [
+ "https://js.moengage.com",
+ "https://cdn.moengage.com",
+ "https://sdk-0X-moengage.com"
+ ]
+ }
+ }
+ ```
+
+7. **Save and Publish**:
+ - Click "Save"
+ - Choose visibility (Private for testing, Public for production)
+
+---
+
+## Step 6: Test in ChatGPT
+
+### 6.1 Access Your GPT
+
+1. **Open ChatGPT**: Go to https://chat.openai.com
+2. **Find Your GPT**: Click on your name → "My GPTs" → Select "Hotel Booking Assistant"
+3. **Start Chat**: Begin a conversation with your GPT
+
+### 6.2 Test Scenarios
+
+#### Scenario 1: Basic Hotel Search
+```
+User: "I want to book a hotel in Paris for next week"
+```
+**Expected**: GPT should use your app to show hotel search interface
+
+#### Scenario 2: Specific Search
+```
+User: "Find hotels in New York from December 15 to December 20 for 2 guests"
+```
+**Expected**: App should display search form with pre-filled data
+
+#### Scenario 3: View Hotel Details
+```
+User: "Show me details about the Grand Plaza Hotel"
+```
+**Expected**: App should show hotel details and booking options
+
+### 6.3 Verify MoEngage Tracking
+
+1. **Open Browser DevTools** (F12)
+2. **Go to Network Tab**
+3. **Filter by "moengage"**
+4. **Perform actions** in the app:
+ - Search for hotels
+ - View hotel details
+ - Start booking
+ - Complete booking
+
+5. **Check MoEngage Dashboard**:
+ - Log in to MoEngage dashboard
+ - Go to "Events" section
+ - Verify events are being tracked:
+ - `app_loaded`
+ - `hotel_search`
+ - `hotel_viewed`
+ - `booking_started`
+ - `booking_completed`
+
+---
+
+## Step 7: Debugging Common Issues
+
+### Issue 1: App Not Loading in ChatGPT
+
+**Symptoms**: Blank screen or error message
+
+**Solutions**:
+- Check CSP headers are correct
+- Verify HTTPS is enabled
+- Check browser console for errors
+- Ensure widget URL is correct in GPT configuration
+
+### Issue 2: MoEngage SDK Not Loading
+
+**Symptoms**: No events in MoEngage dashboard
+
+**Solutions**:
+- Check Network tab for SDK load errors
+- Verify CSP allows `js.moengage.com`
+- Check MoEngage App ID is correct
+- Verify Data Center configuration
+
+### Issue 3: Events Not Tracking
+
+**Symptoms**: Events not appearing in dashboard
+
+**Solutions**:
+- Check browser console for JavaScript errors
+- Verify user is identified (check `identifyUser` calls)
+- Check MoEngage dashboard filters
+- Verify debug logs are enabled
+
+### Issue 4: CORS Errors
+
+**Symptoms**: CORS errors in console
+
+**Solutions**:
+- Add CORS headers in `next.config.js`
+- Verify `Access-Control-Allow-Origin` headers
+- Check MoEngage API endpoints allow your domain
+
+---
+
+## Step 8: Advanced Testing
+
+### 8.1 Test AI Detection
+
+1. **Check AI Detection Component**: The app should detect it's running in ChatGPT
+2. **Verify Attributes**: Check MoEngage dashboard for:
+ - `gpt_app_user: true`
+ - `ai_platform: "chatgpt"`
+ - `is_gpt_app: true`
+
+### 8.2 Test User Identification
+
+1. **Fill User Profile** in the sidebar
+2. **Click "Identify User"**
+3. **Verify in MoEngage**: User should appear in "Users" section
+
+### 8.3 Test Event Tracking
+
+1. **Perform Complete Booking Flow**:
+ - Search hotels
+ - Select hotel
+ - Fill booking form
+ - Complete booking
+
+2. **Verify Events**:
+ - `hotel_search`
+ - `hotel_search_results`
+ - `hotel_viewed`
+ - `booking_started`
+ - `booking_completed`
+
+---
+
+## Step 9: Production Checklist
+
+Before going live:
+
+- [ ] App deployed to production URL
+- [ ] MoEngage App ID configured correctly
+- [ ] CSP headers configured for ChatGPT
+- [ ] Widget CSP configured in GPT settings
+- [ ] HTTPS enabled
+- [ ] All events tracking correctly
+- [ ] User identification working
+- [ ] AI detection working
+- [ ] Error handling in place
+- [ ] Analytics dashboard configured
+
+---
+
+## Step 10: Monitoring and Analytics
+
+### 10.1 MoEngage Dashboard
+
+Monitor:
+- **Events**: Track all user interactions
+- **Users**: Monitor user identification
+- **Segments**: Create segments for GPT app users
+- **Journeys**: Create engagement journeys
+
+### 10.2 Key Metrics to Track
+
+- Number of hotel searches
+- Hotel views
+- Booking completion rate
+- Average booking value
+- GPT app vs web app usage
+
+---
+
+## Troubleshooting Quick Reference
+
+| Issue | Quick Fix |
+|-------|-----------|
+| App won't load | Check CSP headers and HTTPS |
+| SDK not loading | Verify CSP allows MoEngage domains |
+| Events not tracking | Check App ID and Data Center |
+| CORS errors | Add CORS headers in next.config.js |
+| Widget not showing | Verify widget URL in GPT config |
+
+---
+
+## Support Resources
+
+- **MoEngage Docs**: https://docs.moengage.com/
+- **OpenAI GPTs Docs**: https://platform.openai.com/docs/guides/gpts
+- **Next.js Docs**: https://nextjs.org/docs
+- **Vercel Deployment**: https://vercel.com/docs
+
+---
+
+## Next Steps
+
+1. ✅ Deploy your app
+2. ✅ Create ChatGPT GPT
+3. ✅ Configure widget and CSP
+4. ✅ Test all scenarios
+5. ✅ Verify MoEngage tracking
+6. ✅ Monitor analytics
+7. ✅ Iterate and improve
+
+Good luck with your ChatGPT app! 🚀
+
diff --git a/chatgpt-app-sample/DEPLOYMENT_INSTRUCTIONS.md b/chatgpt-app-sample/DEPLOYMENT_INSTRUCTIONS.md
new file mode 100644
index 00000000..899cfb95
--- /dev/null
+++ b/chatgpt-app-sample/DEPLOYMENT_INSTRUCTIONS.md
@@ -0,0 +1,188 @@
+# Deployment Instructions
+
+## Option 1: Deploy via Vercel Dashboard (Recommended - No CLI needed)
+
+### Step 1: Push to GitHub
+
+1. Create a new repository on GitHub
+2. Push your code:
+ ```bash
+ git init
+ git add .
+ git commit -m "Initial commit"
+ git remote add origin https://github.com/YOUR_USERNAME/YOUR_REPO.git
+ git push -u origin main
+ ```
+
+### Step 2: Deploy on Vercel
+
+1. Go to [https://vercel.com](https://vercel.com)
+2. Sign up/Login with your GitHub account
+3. Click **"New Project"**
+4. Import your GitHub repository
+5. Configure project:
+ - **Framework Preset:** Next.js (auto-detected)
+ - **Root Directory:** `./` (default)
+ - **Build Command:** `npm run build` (default)
+ - **Output Directory:** `.next` (default)
+6. Add Environment Variables:
+ - Click **"Environment Variables"**
+ - Add:
+ - **Name:** `NEXT_PUBLIC_MOENGAGE_DATACENTER`
+ - **Value:** `dc_01`
+ - Add:
+ - **Name:** `NEXT_PUBLIC_MOENGAGE_APP_ID`
+ - **Value:** `3RADPYNEBZ2MCOJ43EEW5FWV`
+7. Click **"Deploy"**
+8. Wait for deployment to complete
+9. Note your deployment URL (e.g., `https://your-app.vercel.app`)
+
+### Step 3: Update ChatGPT Manifest
+
+1. After deployment, update `public/.well-known/openai-apps.json`:
+ ```json
+ {
+ "homepage_url": "https://your-app.vercel.app",
+ ...
+ }
+ ```
+2. Commit and push the change
+3. Vercel will automatically redeploy
+
+### Step 4: Verify Manifest
+
+1. Open: `https://your-app.vercel.app/.well-known/openai-apps.json`
+2. Should see the JSON file
+3. Verify `homepage_url` matches your Vercel URL
+
+---
+
+## Option 2: Deploy via Vercel CLI (If SSL issue is resolved)
+
+### Step 1: Login to Vercel
+
+```bash
+vercel login
+```
+
+### Step 2: Deploy
+
+```bash
+vercel --prod
+```
+
+Follow the prompts:
+- Set up and deploy? **Yes**
+- Which scope? (Select your account)
+- Link to existing project? **No**
+- Project name? (Press Enter for default)
+- Directory? (Press Enter for current directory)
+
+### Step 3: Set Environment Variables
+
+```bash
+vercel env add NEXT_PUBLIC_MOENGAGE_DATACENTER
+# Enter: dc_01
+
+vercel env add NEXT_PUBLIC_MOENGAGE_APP_ID
+# Enter: 3RADPYNEBZ2MCOJ43EEW5FWV
+```
+
+### Step 4: Redeploy
+
+```bash
+vercel --prod
+```
+
+---
+
+## Option 3: Deploy to Other Platforms
+
+### Netlify
+
+1. Go to [https://netlify.com](https://netlify.com)
+2. Drag and drop your `.next` folder (after `npm run build`)
+3. Or connect GitHub repository
+4. Set environment variables in Netlify dashboard
+5. Deploy
+
+### Railway
+
+1. Go to [https://railway.app](https://railway.app)
+2. Create new project from GitHub
+3. Set environment variables
+4. Deploy
+
+### Render
+
+1. Go to [https://render.com](https://render.com)
+2. Create new Web Service
+3. Connect GitHub repository
+4. Set environment variables
+5. Deploy
+
+---
+
+## After Deployment
+
+### 1. Update ChatGPT App Manifest
+
+Edit `public/.well-known/openai-apps.json` and set:
+```json
+{
+ "homepage_url": "https://YOUR-DEPLOYMENT-URL.com"
+}
+```
+
+### 2. Register with OpenAI
+
+1. Go to [https://platform.openai.com](https://platform.openai.com)
+2. Navigate to Apps section
+3. Create new app
+4. Set manifest URL: `https://YOUR-DEPLOYMENT-URL.com/.well-known/openai-apps.json`
+
+### 3. Test Deployment
+
+1. Open your deployment URL
+2. Verify app loads correctly
+3. Check MoEngage SDK initializes
+4. Test tracking events
+5. Verify in MoEngage dashboard
+
+---
+
+## Troubleshooting
+
+### SSL Certificate Error (CLI)
+
+If you get SSL certificate errors with Vercel CLI:
+- Use Option 1 (Dashboard deployment) instead
+- Or check your network/proxy settings
+- Or try: `NODE_TLS_REJECT_UNAUTHORIZED=0 vercel --prod` (not recommended for production)
+
+### Environment Variables Not Working
+
+- Ensure variables start with `NEXT_PUBLIC_` for client-side access
+- Redeploy after adding environment variables
+- Check Vercel dashboard → Settings → Environment Variables
+
+### Manifest Not Accessible
+
+- Ensure file is in `public/.well-known/` directory
+- Check file permissions
+- Verify URL is correct: `https://your-app.vercel.app/.well-known/openai-apps.json`
+
+---
+
+## Quick Reference
+
+**Your MoEngage Credentials:**
+- Data Center: `dc_01`
+- App ID: `3RADPYNEBZ2MCOJ43EEW5FWV`
+
+**Environment Variables to Set:**
+```
+NEXT_PUBLIC_MOENGAGE_DATACENTER=dc_01
+NEXT_PUBLIC_MOENGAGE_APP_ID=3RADPYNEBZ2MCOJ43EEW5FWV
+```
+
diff --git a/chatgpt-app-sample/DEPLOYMENT_READY.md b/chatgpt-app-sample/DEPLOYMENT_READY.md
new file mode 100644
index 00000000..52a7cc1c
--- /dev/null
+++ b/chatgpt-app-sample/DEPLOYMENT_READY.md
@@ -0,0 +1,220 @@
+# ✅ Your App is Ready for Deployment!
+
+## Current Status
+
+✅ **Project built successfully**
+✅ **All files committed**
+✅ **Environment variables configured**
+✅ **GitHub repository connected**
+
+---
+
+## 🚀 Next Steps to Deploy
+
+### Option A: Deploy via Vercel Dashboard (Easiest)
+
+1. **Push to GitHub** (if you want to deploy from GitHub):
+ ```bash
+ git push origin feat/chatgpt-app-integration
+ ```
+
+2. **Go to Vercel Dashboard**:
+ - Visit: **https://vercel.com/new**
+ - Click **"Import Git Repository"**
+ - Select: `moengage/webSDK-sample`
+ - Branch: `feat/chatgpt-app-integration`
+
+3. **Configure Project**:
+ - Framework: **Next.js** (auto-detected)
+ - Root Directory: **./**
+ - **Add Environment Variables**:
+ ```
+ NEXT_PUBLIC_MOENGAGE_DATACENTER=dc_01
+ NEXT_PUBLIC_MOENGAGE_APP_ID=3RADPYNEBZ2MCOJ43EEW5FWV
+ ```
+
+4. **Deploy**:
+ - Click **"Deploy"**
+ - Wait 2-3 minutes
+ - **Copy your deployment URL** (e.g., `https://websdk-sample-xyz.vercel.app`)
+
+5. **Update Config Files**:
+ - Update `public/ai-plugin.json` with your Vercel URL
+ - Update `public/.well-known/openapi.yaml` with your Vercel URL
+ - Commit and push:
+ ```bash
+ git add .
+ git commit -m "Update deployment URLs"
+ git push
+ ```
+
+---
+
+### Option B: Deploy via Vercel CLI
+
+1. **Login to Vercel**:
+ ```bash
+ vercel login
+ ```
+ (This will open browser for authentication)
+
+2. **Deploy**:
+ ```bash
+ cd /Users/aman.verma/Desktop/Projects/OPEN_AI_SDK/chatgpt-app-sample
+ vercel
+ ```
+
+3. **Follow prompts**:
+ - Link to existing? → **N**
+ - Project name → Press **Enter**
+ - Directory → Press **Enter**
+ - Override? → **N**
+
+4. **Add Environment Variables in Dashboard**:
+ - Go to: https://vercel.com/dashboard
+ - Select your project
+ - **Settings** → **Environment Variables**
+ - Add both variables
+ - **Redeploy**
+
+---
+
+## 🤖 After Deployment: Create ChatGPT GPT
+
+1. **Go to OpenAI Platform**: https://platform.openai.com/
+2. **Click "GPTs"** → **"Create"**
+3. **Configure**:
+ - **Name**: `Hotel Booking Assistant`
+ - **Description**: `Helps users search and book hotels`
+ - **Instructions**:
+ ```
+ You are a helpful hotel booking assistant. When users ask about hotels,
+ help them search for available hotels by destination, dates, and number of guests.
+ Use the hotel booking widget to show them options and help them complete bookings.
+ ```
+
+4. **Add Widget**:
+ - Scroll to **"Widget"** section
+ - **Widget URL**: `https://YOUR-VERCEL-URL.vercel.app`
+ - **Widget CSP** (optional):
+ ```json
+ {
+ "openai/widgetCSP": {
+ "connect_domains": [
+ "https://*.moengage.com",
+ "https://api.moengage.com"
+ ],
+ "resource_domains": [
+ "https://js.moengage.com",
+ "https://cdn.moengage.com"
+ ]
+ }
+ }
+ ```
+
+5. **Save**:
+ - Click **"Save"** (top right)
+ - Choose visibility: **"Only me"** or **"Anyone with a link"**
+
+---
+
+## ✅ Test in ChatGPT
+
+1. **Open ChatGPT**: https://chat.openai.com
+2. **Access Your GPT**:
+ - Click your name (top right)
+ - Click **"My GPTs"**
+ - Select **"Hotel Booking Assistant"**
+
+3. **Test Scenarios**:
+
+ **Test 1: Basic Search**
+ ```
+ "I want to book a hotel in Paris for next week"
+ ```
+ - Expected: Widget appears with search form
+
+ **Test 2: Specific Search**
+ ```
+ "Find hotels in New York from December 20 to December 25 for 2 guests"
+ ```
+ - Expected: Search form with pre-filled dates
+
+ **Test 3: Complete Booking Flow**
+ - Search for hotels
+ - Click on a hotel
+ - Fill booking form
+ - Complete booking
+
+---
+
+## 📊 Verify MoEngage Tracking
+
+1. **Open Browser DevTools**:
+ - Press `F12` or `Cmd+Option+I`
+ - Go to **"Network"** tab
+ - Filter by: `moengage`
+
+2. **Perform Actions**:
+ - Search for hotels
+ - View hotel details
+ - Start booking
+ - Complete booking
+
+3. **Check Network Requests**:
+ - You should see requests to `*.moengage.com`
+ - Check request payloads contain event data
+
+4. **Check MoEngage Dashboard**:
+ - Login: https://app.moengage.com/
+ - Go to **"Analytics"** → **"Events"**
+ - Look for events:
+ - `app_loaded`
+ - `hotel_search`
+ - `hotel_viewed`
+ - `booking_started`
+ - `booking_completed`
+ - `gpt_app_session_start`
+
+5. **Verify User Attributes**:
+ - Go to **"Users"** section
+ - Check for:
+ - `gpt_app_user: true`
+ - `ai_platform: "chatgpt"`
+ - `is_gpt_app: true`
+
+---
+
+## 🐛 Troubleshooting
+
+### Widget Not Showing?
+- Check Widget URL is correct
+- Check browser console for errors
+- Verify HTTPS is enabled
+- Check CSP headers
+
+### MoEngage Not Tracking?
+- Check Network tab for SDK loading
+- Verify App ID is correct
+- Check CSP allows MoEngage domains
+- Verify environment variables in Vercel
+
+### Events Not in Dashboard?
+- Wait 1-2 minutes (events may be delayed)
+- Check dashboard filters
+- Verify you're looking at correct app
+- Check browser console for errors
+
+---
+
+## 📚 Documentation
+
+- **Quick Deploy**: `QUICK_DEPLOY.md`
+- **Testing Steps**: `TESTING_STEPS.md`
+- **Full Guide**: `CHATGPT_TESTING_GUIDE.md`
+- **Tracking Details**: `MOENGAGE_TRACKING.md`
+
+---
+
+**Ready to deploy? Choose Option A or B above and follow the steps!** 🚀
+
diff --git a/chatgpt-app-sample/DEPLOY_NOW.md b/chatgpt-app-sample/DEPLOY_NOW.md
new file mode 100644
index 00000000..771bee1f
--- /dev/null
+++ b/chatgpt-app-sample/DEPLOY_NOW.md
@@ -0,0 +1,105 @@
+# Quick Deployment & Testing Guide
+
+## 🚀 Step 1: Create Environment File
+
+Create `.env.local` file in the project root:
+
+```bash
+NEXT_PUBLIC_MOENGAGE_DATACENTER=dc_01
+NEXT_PUBLIC_MOENGAGE_APP_ID=3RADPYNEBZ2MCOJ43EEW5FWV
+```
+
+## 🚀 Step 2: Deploy to Vercel
+
+Run these commands:
+
+```bash
+cd /Users/aman.verma/Desktop/Projects/OPEN_AI_SDK/chatgpt-app-sample
+
+# Login to Vercel (if not logged in)
+vercel login
+
+# Deploy
+vercel
+```
+
+**When prompted:**
+- Link to existing project? → **N** (first time)
+- Project name → **hotel-booking-app** (or press Enter)
+- Directory → **./** (press Enter)
+- Override settings? → **N** (press Enter)
+
+**After deployment:**
+- Copy the deployment URL (e.g., `https://hotel-booking-app-xyz.vercel.app`)
+- You'll need this URL in the next steps!
+
+## 🔧 Step 3: Add Environment Variables in Vercel
+
+1. Go to: https://vercel.com/dashboard
+2. Click on your project
+3. Go to **Settings** → **Environment Variables**
+4. Add these:
+ - **Name**: `NEXT_PUBLIC_MOENGAGE_DATACENTER`
+ - **Value**: `dc_01`
+ - Click **Save**
+
+ - **Name**: `NEXT_PUBLIC_MOENGAGE_APP_ID`
+ - **Value**: `3RADPYNEBZ2MCOJ43EEW5FWV`
+ - Click **Save**
+
+5. Go to **Deployments** tab
+6. Click **"..."** on latest deployment → **Redeploy**
+
+## 📝 Step 4: Update Configuration Files
+
+After deployment, update these files with your **actual Vercel URL**:
+
+### Update `public/ai-plugin.json`:
+Replace `https://your-app.vercel.app` with your actual URL
+
+### Update `public/.well-known/openapi.yaml`:
+Replace `https://your-app.vercel.app` with your actual URL
+
+### Then redeploy:
+```bash
+vercel --prod
+```
+
+## 🤖 Step 5: Create ChatGPT GPT
+
+1. Go to: https://platform.openai.com/
+2. Click **"GPTs"** → **"Create"**
+3. **Configure**:
+ - Name: `Hotel Booking Assistant`
+ - Instructions: `You are a hotel booking assistant. Help users search and book hotels.`
+4. **Add Widget**:
+ - Widget URL: `https://YOUR-VERCEL-URL.vercel.app`
+ - Widget CSP (if available):
+ ```json
+ {
+ "openai/widgetCSP": {
+ "connect_domains": ["https://*.moengage.com"],
+ "resource_domains": ["https://js.moengage.com", "https://cdn.moengage.com"]
+ }
+ }
+ ```
+5. Click **"Save"**
+
+## ✅ Step 6: Test in ChatGPT
+
+1. Go to: https://chat.openai.com
+2. Click your name → **"My GPTs"** → **"Hotel Booking Assistant"**
+3. Try: `"I want to book a hotel in Paris for next week"`
+4. Widget should appear!
+
+## 📊 Step 7: Verify MoEngage
+
+1. Open DevTools (F12) → Network tab
+2. Filter: `moengage`
+3. Perform actions in the app
+4. Check MoEngage Dashboard: https://app.moengage.com/
+
+---
+
+**Need help?** See `TESTING_STEPS.md` for detailed instructions.
+
diff --git a/chatgpt-app-sample/IMPLEMENTATION_SUMMARY.md b/chatgpt-app-sample/IMPLEMENTATION_SUMMARY.md
new file mode 100644
index 00000000..3adf3a56
--- /dev/null
+++ b/chatgpt-app-sample/IMPLEMENTATION_SUMMARY.md
@@ -0,0 +1,169 @@
+# Implementation Summary
+
+## What Was Done
+
+### 1. ✅ Transformed App into Booking.com-like Interface
+
+**Created New Components:**
+- `HotelSearch.tsx` - Search form for destination, dates, and guests
+- `HotelResults.tsx` - Display hotel listings with images, ratings, and prices
+- `HotelBooking.tsx` - Complete booking form with guest information
+- `UserProfile.tsx` - User identification component (moved to sidebar)
+
+**Updated Main Page:**
+- Complete redesign with booking.com-style layout
+- Grid-based responsive design
+- Header with MoEngage status indicator
+- Sidebar for user profile and tracking logs
+
+**Styling:**
+- Booking.com color scheme (#003580 blue)
+- Professional hotel card layouts
+- Responsive design for mobile and desktop
+- Modern UI with shadows and hover effects
+
+### 2. ✅ MoEngage SDK Integration
+
+**Updated `lib/moengage.ts`:**
+- Using staging SDK URL: `https://js.moengage.com/staging/versions/5.02.45/sdk.js`
+- Improved initialization logic
+- Better error handling
+
+**Event Tracking:**
+- `app_loaded` - When app initializes
+- `hotel_search` - When user searches for hotels
+- `hotel_search_results` - When results are displayed
+- `hotel_viewed` - When user views hotel details
+- `booking_started` - When user starts booking
+- `booking_completed` - When booking is confirmed
+
+**User Attributes:**
+- `ai_assisted` - Set when AI-assisted browser detected
+- `gpt_app_user` - Set when running in ChatGPT
+- `ai_platform` - Tracks platform (chatgpt/web)
+
+### 3. ✅ ChatGPT Integration Setup
+
+**Configuration Files:**
+- `public/ai-plugin.json` - ChatGPT plugin manifest
+- `public/.well-known/openapi.yaml` - OpenAPI specification
+- Updated `next.config.js` - CSP headers for ChatGPT
+- Updated `app/layout.tsx` - CSP meta tags
+
+**Content Security Policy:**
+- Allows ChatGPT domains to embed the app
+- Allows MoEngage SDK to load
+- Allows MoEngage API connections
+
+### 4. ✅ Comprehensive Testing Guide
+
+**Created `CHATGPT_TESTING_GUIDE.md` with:**
+- Step-by-step deployment instructions
+- ChatGPT GPT creation guide
+- Widget configuration
+- CSP setup instructions
+- Testing scenarios
+- Debugging guide
+- Production checklist
+
+## Key Features
+
+### Hotel Booking Flow
+1. **Search**: User enters destination, dates, guests
+2. **Results**: Display hotels with images, ratings, prices
+3. **Details**: Click hotel to view details
+4. **Booking**: Fill guest information and complete booking
+5. **Tracking**: All steps tracked in MoEngage
+
+### AI Detection
+- **Bot Detection**: Blocks known AI bots (GPTBot, ClaudeBot, etc.)
+- **AI-Assisted Detection**: Identifies AI-assisted browsers
+- **GPT App Detection**: Detects when running in ChatGPT
+- **Automatic Attributes**: Sets user attributes based on detection
+
+### MoEngage Tracking
+- Real-time event tracking
+- User identification
+- Session management
+- Tracking logs in sidebar
+
+## File Structure
+
+```
+chatgpt-app-sample/
+├── app/
+│ ├── page.tsx # Main booking page
+│ ├── page.module.css # Page styles
+│ ├── layout.tsx # Root layout with CSP
+│ └── globals.css # Global styles
+├── components/
+│ ├── HotelSearch.tsx # Search form
+│ ├── HotelSearch.module.css
+│ ├── HotelResults.tsx # Hotel listings
+│ ├── HotelResults.module.css
+│ ├── HotelBooking.tsx # Booking form
+│ ├── HotelBooking.module.css
+│ ├── UserProfile.tsx # User identification
+│ ├── UserProfile.module.css
+│ └── TrackingLogs.tsx # Event logs
+├── lib/
+│ ├── moengage.ts # MoEngage SDK wrapper
+│ ├── ai-detection.ts # AI detection logic
+│ └── chatgpt-apps.ts # ChatGPT Apps SDK
+├── hooks/
+│ ├── useMoEngage.ts # MoEngage hook
+│ ├── useTracking.ts # Tracking hook
+│ └── useAIDetection.ts # AI detection hook
+├── public/
+│ ├── ai-plugin.json # ChatGPT plugin config
+│ └── .well-known/
+│ └── openapi.yaml # OpenAPI spec
+├── CHATGPT_TESTING_GUIDE.md # Complete testing guide
+├── QUICK_START.md # Quick start guide
+└── README.md # Updated README
+```
+
+## Next Steps
+
+1. **Deploy to Vercel**:
+ ```bash
+ npm install -g vercel
+ vercel
+ ```
+
+2. **Update Configuration Files**:
+ - Update `public/ai-plugin.json` with your deployment URL
+ - Update `public/.well-known/openapi.yaml` with your deployment URL
+
+3. **Create ChatGPT GPT**:
+ - Follow `CHATGPT_TESTING_GUIDE.md` Step 5
+
+4. **Test in ChatGPT**:
+ - Follow `CHATGPT_TESTING_GUIDE.md` Step 6
+
+5. **Verify MoEngage Tracking**:
+ - Check MoEngage dashboard for events
+ - Verify user identification
+ - Check AI detection attributes
+
+## Environment Variables
+
+Create `.env.local`:
+
+```env
+NEXT_PUBLIC_MOENGAGE_DATACENTER=dc_01
+NEXT_PUBLIC_MOENGAGE_APP_ID=3RADPYNEBZ2MCOJ43EEW5FWV
+```
+
+## MoEngage SDK
+
+- **Version**: Staging 5.02.45
+- **URL**: `https://js.moengage.com/staging/versions/5.02.45/sdk.js`
+- **Features**: Full tracking, user identification, AI detection
+
+## Support
+
+- **ChatGPT Testing**: See `CHATGPT_TESTING_GUIDE.md`
+- **Quick Start**: See `QUICK_START.md`
+- **Deployment**: See `DEPLOYMENT_INSTRUCTIONS.md`
+
diff --git a/chatgpt-app-sample/INTEGRATION_EXAMPLES.md b/chatgpt-app-sample/INTEGRATION_EXAMPLES.md
new file mode 100644
index 00000000..2a53b8c5
--- /dev/null
+++ b/chatgpt-app-sample/INTEGRATION_EXAMPLES.md
@@ -0,0 +1,280 @@
+# Integration Examples
+
+## Example 1: E-commerce Product Tracking
+
+```javascript
+// Track product view
+trackingManager.trackEvent('product_view', {
+ product_id: 'PROD123',
+ product_name: 'Wireless Headphones',
+ product_category: 'Electronics',
+ product_price: 199.99,
+ currency: 'USD',
+ brand: 'TechBrand'
+});
+
+// Track add to cart
+trackingManager.trackEvent('add_to_cart', {
+ product_id: 'PROD123',
+ product_name: 'Wireless Headphones',
+ quantity: 2,
+ price: 199.99,
+ currency: 'USD',
+ cart_value: 399.98
+});
+
+// Track purchase
+trackingManager.trackEvent('purchase', {
+ order_id: 'ORD789',
+ product_id: 'PROD123',
+ product_name: 'Wireless Headphones',
+ quantity: 2,
+ total_amount: 399.98,
+ currency: 'USD',
+ payment_method: 'credit_card',
+ shipping_method: 'express'
+});
+```
+
+## Example 2: User Journey Tracking
+
+```javascript
+// Identify user on login
+trackingManager.handleIdentifyUser();
+
+// Track key milestones
+trackingManager.trackEvent('user_signed_up', {
+ signup_method: 'email',
+ referral_source: 'organic'
+});
+
+trackingManager.trackEvent('onboarding_completed', {
+ steps_completed: 5,
+ time_taken: 120
+});
+
+trackingManager.trackEvent('feature_used', {
+ feature_name: 'advanced_search',
+ usage_count: 3
+});
+```
+
+## Example 3: AI-Assisted User Segmentation
+
+```javascript
+// The app automatically detects AI-assisted browsers
+// You can use this in MoEngage to create segments:
+
+// Segment 1: AI-Assisted Users
+// Condition: ai_assisted_browser == true
+
+// Segment 2: GPT App Users
+// Condition: gpt_app_user == true
+
+// Segment 3: High-Intent AI Users
+// Condition: ai_assisted_browser == true AND purchase_count > 0
+
+// Track specific events for AI-assisted users
+if (aiDetection.getDetectionResults().isAIAssisted) {
+ trackingManager.trackEvent('ai_assisted_interaction', {
+ interaction_type: 'product_search',
+ ai_features_used: ['voice_search', 'smart_suggestions']
+ });
+}
+```
+
+## Example 4: Custom Event with Rich Properties
+
+```javascript
+// Track a custom event with detailed properties
+trackingManager.trackEvent('content_engagement', {
+ content_type: 'article',
+ content_id: 'ART456',
+ content_title: 'How to Use AI in Marketing',
+ reading_time: 180,
+ scroll_depth: 85,
+ shares: 3,
+ likes: 12,
+ comments: 5
+});
+```
+
+## Example 5: Form Tracking
+
+```javascript
+// Track form submissions
+trackingManager.trackEvent('form_submitted', {
+ form_type: 'contact',
+ form_id: 'contact_form_1',
+ fields_completed: 5,
+ time_to_complete: 45,
+ submission_successful: true
+});
+
+// Track form abandonment
+trackingManager.trackEvent('form_abandoned', {
+ form_type: 'checkout',
+ form_id: 'checkout_form',
+ fields_completed: 3,
+ total_fields: 8,
+ abandonment_reason: 'timeout'
+});
+```
+
+## Example 6: Search and Discovery
+
+```javascript
+// Track search queries
+trackingManager.trackEvent('search', {
+ search_query: 'wireless headphones',
+ search_category: 'electronics',
+ results_count: 24,
+ filters_applied: ['price_range', 'brand'],
+ search_source: 'header'
+});
+
+// Track search result clicks
+trackingManager.trackEvent('search_result_clicked', {
+ search_query: 'wireless headphones',
+ result_position: 3,
+ result_id: 'PROD123',
+ click_through: true
+});
+```
+
+## Example 7: Campaign Engagement
+
+```javascript
+// MoEngage automatically tracks campaign events
+// But you can also track custom campaign interactions:
+
+trackingManager.trackEvent('campaign_interaction', {
+ campaign_id: 'SUMMER_SALE_2024',
+ campaign_type: 'banner',
+ interaction_type: 'click',
+ campaign_name: 'Summer Sale 2024'
+});
+```
+
+## Example 8: Error and Performance Tracking
+
+```javascript
+// Track errors
+trackingManager.trackEvent('error_occurred', {
+ error_type: 'javascript_error',
+ error_message: 'Failed to load product data',
+ error_location: 'product_page',
+ user_agent: navigator.userAgent
+});
+
+// Track performance
+trackingManager.trackEvent('performance_metric', {
+ metric_name: 'page_load_time',
+ metric_value: 1250,
+ page_url: window.location.href
+});
+```
+
+## Example 9: Multi-Step Process Tracking
+
+```javascript
+// Track multi-step processes
+const steps = ['view_product', 'add_to_cart', 'checkout', 'payment', 'confirmation'];
+
+steps.forEach((step, index) => {
+ trackingManager.trackEvent('checkout_step', {
+ step_name: step,
+ step_number: index + 1,
+ total_steps: steps.length,
+ timestamp: new Date().toISOString()
+ });
+});
+```
+
+## Example 10: Conditional Tracking Based on AI Detection
+
+```javascript
+// Track differently based on AI detection
+const detection = aiDetection.getDetectionResults();
+
+if (detection.isAIBot) {
+ // Don't track - already handled by shouldBlockTracking()
+ console.log('Bot detected - tracking blocked');
+} else if (detection.isGPTApp) {
+ // Enhanced tracking for GPT app users
+ trackingManager.trackEvent('gpt_app_interaction', {
+ interaction_type: 'product_inquiry',
+ gpt_context: 'user_asked_about_product',
+ response_provided: true
+ });
+} else if (detection.isAIAssisted) {
+ // Track AI-assisted features
+ trackingManager.trackEvent('ai_feature_used', {
+ feature_type: 'smart_suggestions',
+ user_satisfaction: 'high'
+ });
+} else {
+ // Standard tracking for regular users
+ trackingManager.trackEvent('standard_interaction', {
+ interaction_type: 'page_view'
+ });
+}
+```
+
+## Example 11: User Attribute Updates
+
+```javascript
+// Update user attributes
+if (typeof Moengage !== 'undefined' && Moengage) {
+ Moengage.add_user_attribute({
+ subscription_status: 'premium',
+ subscription_tier: 'pro',
+ last_purchase_date: '2024-01-15',
+ total_purchases: 5,
+ lifetime_value: 499.95,
+ favorite_category: 'electronics'
+ });
+}
+```
+
+## Example 12: Session-Based Tracking
+
+```javascript
+// Track session start
+trackingManager.trackEvent('session_start', {
+ referrer: document.referrer,
+ landing_page: window.location.href,
+ device_type: /Mobile|Android|iPhone/i.test(navigator.userAgent) ? 'mobile' : 'desktop'
+});
+
+// Track session end (automatically handled on beforeunload)
+// But you can also track manually:
+window.addEventListener('beforeunload', () => {
+ trackingManager.trackEvent('session_end_manual', {
+ session_duration: performance.now(),
+ pages_viewed: 5
+ });
+});
+```
+
+## Best Practices
+
+1. **Always identify users before tracking events** - This ensures proper attribution
+2. **Use consistent event names** - Follow a naming convention (e.g., snake_case)
+3. **Include relevant context** - Add properties that help with analysis
+4. **Respect AI bot detection** - Don't override the blocking mechanism
+5. **Track user journey** - Track key milestones in user flows
+6. **Use custom events wisely** - Don't over-track, focus on meaningful events
+7. **Test in MoEngage dashboard** - Verify events appear correctly
+8. **Monitor event volume** - Be mindful of event limits
+
+## Integration with MoEngage Dashboard
+
+After tracking events, you can:
+
+1. **Create Segments** - Use event properties and user attributes
+2. **Build Journeys** - Create user journey flows based on events
+3. **Set up Campaigns** - Target users based on behavior
+4. **Analyze Funnels** - Track conversion funnels
+5. **Create Reports** - Build custom reports with tracked events
+
diff --git a/chatgpt-app-sample/MANUAL_DEPLOY.md b/chatgpt-app-sample/MANUAL_DEPLOY.md
new file mode 100644
index 00000000..aaeb8383
--- /dev/null
+++ b/chatgpt-app-sample/MANUAL_DEPLOY.md
@@ -0,0 +1,150 @@
+# Manual Deployment Guide (Alternative Method)
+
+Since Vercel CLI has SSL issues, here's how to deploy manually:
+
+## Option 1: Deploy via Vercel Dashboard (Easiest)
+
+### Step 1: Prepare Your Code
+
+1. **Make sure all files are ready**:
+ ```bash
+ cd /Users/aman.verma/Desktop/Projects/OPEN_AI_SDK/chatgpt-app-sample
+ npm run build
+ ```
+
+2. **Create a Git repository** (if not already):
+ ```bash
+ git init
+ git add .
+ git commit -m "Initial commit - Hotel booking app"
+ ```
+
+3. **Push to GitHub**:
+ - Create a new repository on GitHub
+ - Push your code:
+ ```bash
+ git remote add origin https://github.com/YOUR-USERNAME/hotel-booking-app.git
+ git push -u origin main
+ ```
+
+### Step 2: Deploy via Vercel Dashboard
+
+1. **Go to Vercel**: https://vercel.com/new
+
+2. **Import your repository**:
+ - Click "Import Git Repository"
+ - Select your GitHub repository
+ - Click "Import"
+
+3. **Configure Project**:
+ - Framework Preset: **Next.js** (auto-detected)
+ - Root Directory: **./** (leave as is)
+ - Build Command: `npm run build` (default)
+ - Output Directory: `.next` (default)
+
+4. **Add Environment Variables**:
+ - Click "Environment Variables"
+ - Add:
+ - **Name**: `NEXT_PUBLIC_MOENGAGE_DATACENTER`
+ - **Value**: `dc_01`
+ - Click "Add"
+ - Add:
+ - **Name**: `NEXT_PUBLIC_MOENGAGE_APP_ID`
+ - **Value**: `3RADPYNEBZ2MCOJ43EEW5FWV`
+ - Click "Add"
+
+5. **Deploy**:
+ - Click "Deploy"
+ - Wait for deployment to complete (2-3 minutes)
+ - **Copy your deployment URL** (e.g., `https://hotel-booking-app-xyz.vercel.app`)
+
+---
+
+## Option 2: Deploy via Vercel CLI (Fix SSL Issue)
+
+If you want to fix the SSL issue:
+
+### For macOS:
+```bash
+# Install certificates
+brew install ca-certificates
+
+# Or set Node to not reject unauthorized certificates (not recommended for production)
+export NODE_TLS_REJECT_UNAUTHORIZED=0
+vercel
+```
+
+### Or use npm script:
+Add to `package.json`:
+```json
+"scripts": {
+ "deploy": "NODE_TLS_REJECT_UNAUTHORIZED=0 vercel --prod"
+}
+```
+
+Then run:
+```bash
+npm run deploy
+```
+
+---
+
+## After Deployment
+
+### Step 1: Update Configuration Files
+
+1. **Update `public/ai-plugin.json`**:
+ Replace `https://your-app.vercel.app` with your actual Vercel URL
+
+2. **Update `public/.well-known/openapi.yaml`**:
+ Replace `https://your-app.vercel.app` with your actual Vercel URL
+
+3. **Commit and push changes**:
+ ```bash
+ git add .
+ git commit -m "Update deployment URLs"
+ git push
+ ```
+
+4. **Vercel will auto-redeploy** (or manually redeploy from dashboard)
+
+---
+
+## Step 2: Create ChatGPT GPT
+
+1. **Go to OpenAI Platform**: https://platform.openai.com/
+2. **Click "GPTs"** → **"Create"**
+3. **Configure**:
+ - Name: `Hotel Booking Assistant`
+ - Instructions: `You are a hotel booking assistant. Help users search and book hotels.`
+4. **Add Widget**:
+ - Widget URL: `https://YOUR-VERCEL-URL.vercel.app`
+5. **Save**
+
+---
+
+## Step 3: Test
+
+1. Go to: https://chat.openai.com
+2. Click your name → "My GPTs" → "Hotel Booking Assistant"
+3. Try: `"I want to book a hotel in Paris for next week"`
+
+---
+
+## Quick Commands
+
+```bash
+# Build locally
+npm run build
+
+# Test locally
+npm run dev
+
+# Check if ready for deployment
+npm run build && echo "✅ Ready to deploy!"
+```
+
+---
+
+**Recommended**: Use Option 1 (Vercel Dashboard) - it's the easiest and most reliable method!
+
diff --git a/chatgpt-app-sample/MOENGAGE_TRACKING.md b/chatgpt-app-sample/MOENGAGE_TRACKING.md
new file mode 100644
index 00000000..1b97a4e2
--- /dev/null
+++ b/chatgpt-app-sample/MOENGAGE_TRACKING.md
@@ -0,0 +1,596 @@
+# MoEngage Tracking Implementation Guide
+
+This document details all MoEngage events and user attributes tracked in the hotel booking app.
+
+## Event Tracking Overview
+
+The app tracks comprehensive user interactions throughout the entire booking journey, from initial search to booking completion.
+
+---
+
+## Core Events
+
+### 1. App Lifecycle Events
+
+#### `app_loaded`
+**Triggered**: When the app initializes and MoEngage SDK is ready
+
+**Properties**:
+```javascript
+{
+ load_time: number, // Time taken to load (ms)
+ page: 'home', // Current page
+ ai_platform: 'chatgpt' | 'web',
+ is_ai_assisted: boolean,
+ is_gpt_app: boolean,
+ timestamp: string
+}
+```
+
+#### `chatgpt_app_initialized`
+**Triggered**: When ChatGPT Apps SDK is successfully initialized
+
+**Properties**:
+```javascript
+{
+ ai_platform: 'chatgpt',
+ is_gpt_app: true,
+ timestamp: string
+}
+```
+
+#### `chatgpt_action`
+**Triggered**: When user interacts with ChatGPT app interface
+
+**Properties**:
+```javascript
+{
+ action_type: string, // Type of ChatGPT action
+ action_data: string, // JSON stringified action data
+ timestamp: string
+}
+```
+
+#### `session_end`
+**Triggered**: When user leaves/closes the app
+
+**Properties**:
+```javascript
+{
+ session_duration: number, // Session duration in ms
+ timestamp: string
+}
+```
+
+---
+
+### 2. Search Events
+
+#### `search_form_viewed`
+**Triggered**: When search form is displayed
+
+**Properties**:
+```javascript
+{
+ page: 'home',
+ component: 'hotel_search',
+ timestamp: string
+}
+```
+
+#### `search_form_submitted`
+**Triggered**: When user submits search form
+
+**Properties**:
+```javascript
+{
+ destination: string, // Search destination
+ check_in: string, // Check-in date (YYYY-MM-DD)
+ check_out: string, // Check-out date (YYYY-MM-DD)
+ guests: number, // Number of guests
+ nights: number, // Calculated number of nights
+ timestamp: string
+}
+```
+
+#### `search_form_error`
+**Triggered**: When search form submission fails validation
+
+**Properties**:
+```javascript
+{
+ error_type: 'missing_fields',
+ has_destination: boolean,
+ has_check_in: boolean,
+ has_check_out: boolean,
+ timestamp: string
+}
+```
+
+#### `hotel_search`
+**Triggered**: When search is executed (after form submission)
+
+**Properties**:
+```javascript
+{
+ destination: string,
+ check_in: string,
+ check_out: string,
+ guests: number,
+ ai_platform: 'chatgpt' | 'web',
+ is_ai_assisted: boolean,
+ is_gpt_app: boolean,
+ timestamp: string
+}
+```
+
+#### `hotel_search_results`
+**Triggered**: When search results are displayed
+
+**Properties**:
+```javascript
+{
+ destination: string,
+ results_count: number, // Number of hotels found
+ timestamp: string
+}
+```
+
+---
+
+### 3. Hotel Listing Events
+
+#### `hotel_results_viewed`
+**Triggered**: When hotel results page is displayed
+
+**Properties**:
+```javascript
+{
+ destination: string,
+ results_count: number,
+ check_in: string,
+ check_out: string,
+ nights: number,
+ guests: number,
+ timestamp: string
+}
+```
+
+#### `hotel_impression`
+**Triggered**: For each hotel displayed in results (one per hotel)
+
+**Properties**:
+```javascript
+{
+ hotel_id: string,
+ hotel_name: string,
+ hotel_price: number,
+ hotel_rating: number,
+ position: number, // Position in results (1, 2, 3...)
+ destination: string,
+ timestamp: string
+}
+```
+
+#### `hotel_card_clicked`
+**Triggered**: When user clicks on a hotel card
+
+**Properties**:
+```javascript
+{
+ hotel_id: string,
+ hotel_name: string,
+ hotel_price: number,
+ hotel_rating: number,
+ position: number, // Position in results
+ destination: string,
+ timestamp: string
+}
+```
+
+#### `hotel_viewed`
+**Triggered**: When user views hotel details (selects a hotel)
+
+**Properties**:
+```javascript
+{
+ hotel_id: string,
+ hotel_name: string,
+ hotel_price: number,
+ hotel_rating: number,
+ hotel_location: string,
+ hotel_amenities: string, // Comma-separated amenities
+ destination: string,
+ check_in: string,
+ check_out: string,
+ nights: number,
+ guests: number,
+ estimated_total: number, // Price × nights
+ timestamp: string
+}
+```
+
+---
+
+### 4. Booking Flow Events
+
+#### `booking_flow_started`
+**Triggered**: When user starts booking process
+
+**Properties**:
+```javascript
+{
+ hotel_id: string,
+ hotel_name: string,
+ step: 'hotel_selected',
+ timestamp: string
+}
+```
+
+#### `booking_page_viewed`
+**Triggered**: When booking form page is displayed
+
+**Properties**:
+```javascript
+{
+ hotel_id: string,
+ hotel_name: string,
+ hotel_price: number,
+ check_in: string,
+ check_out: string,
+ guests: number,
+ nights: number,
+ total_amount: number,
+ timestamp: string
+}
+```
+
+#### `booking_form_field_changed`
+**Triggered**: When user types in any booking form field
+
+**Properties**:
+```javascript
+{
+ field_name: 'first_name' | 'last_name' | 'email' | 'phone',
+ has_value: boolean,
+ hotel_id: string,
+ timestamp: string
+}
+```
+
+#### `payment_method_selected`
+**Triggered**: When user selects payment method
+
+**Properties**:
+```javascript
+{
+ payment_method: 'credit_card' | 'paypal',
+ hotel_id: string,
+ timestamp: string
+}
+```
+
+#### `booking_started`
+**Triggered**: When user submits booking form
+
+**Properties**:
+```javascript
+{
+ hotel_id: string,
+ hotel_name: string,
+ hotel_price: number,
+ total_amount: number,
+ subtotal: number,
+ tax: number,
+ nights: number,
+ guests: number,
+ check_in: string,
+ check_out: string,
+ payment_method: string,
+ has_email: boolean,
+ has_phone: boolean,
+ timestamp: string
+}
+```
+
+#### `booking_completed`
+**Triggered**: When booking is successfully completed
+
+**Properties**:
+```javascript
+{
+ hotel_id: string,
+ hotel_name: string,
+ hotel_price: number,
+ hotel_rating: number,
+ booking_id: string, // Unique booking ID
+ total_amount: number,
+ subtotal: number,
+ tax: number,
+ nights: number,
+ check_in: string,
+ check_out: string,
+ guests: number,
+ destination: string,
+ currency: 'USD',
+ booking_timestamp: string,
+ timestamp: string
+}
+```
+
+#### `conversion`
+**Triggered**: When booking is completed (revenue event)
+
+**Properties**:
+```javascript
+{
+ conversion_type: 'hotel_booking',
+ booking_id: string,
+ revenue: number, // Total booking amount
+ hotel_id: string,
+ timestamp: string
+}
+```
+
+#### `booking_cancelled`
+**Triggered**: When user cancels booking process
+
+**Properties**:
+```javascript
+{
+ hotel_id: string,
+ hotel_name: string,
+ total_amount: number,
+ form_progress: {
+ has_first_name: boolean,
+ has_last_name: boolean,
+ has_email: boolean,
+ has_phone: boolean
+ },
+ timestamp: string
+}
+```
+
+#### `booking_flow_exited`
+**Triggered**: When user exits booking flow
+
+**Properties**:
+```javascript
+{
+ hotel_id: string,
+ step: 'booking_form',
+ timestamp: string
+}
+```
+
+---
+
+### 5. User Identification Events
+
+#### `user_identified`
+**Triggered**: When user is identified via UserProfile component
+
+**Properties**:
+```javascript
+{
+ has_name: boolean,
+ has_email: boolean,
+ has_mobile: boolean,
+ timestamp: string
+}
+```
+
+#### `user_id_updated`
+**Triggered**: When user ID is updated
+
+**Properties**:
+```javascript
+{
+ new_user_id: string,
+ timestamp: string
+}
+```
+
+#### `session_destroyed`
+**Triggered**: When session is destroyed/logged out
+
+**Properties**:
+```javascript
+{
+ timestamp: string
+}
+```
+
+---
+
+### 6. AI Detection Events
+
+#### `ai_detection_performed`
+**Triggered**: When AI detection runs on app load
+
+**Properties**:
+```javascript
+{
+ is_ai_bot: boolean,
+ is_ai_assisted: boolean,
+ is_gpt_app: boolean,
+ detection_details: string, // JSON stringified details
+ timestamp: string
+}
+```
+
+#### `gpt_app_session_start`
+**Triggered**: When app detects it's running in ChatGPT
+
+**Properties**:
+```javascript
+{
+ app_url: string,
+ timestamp: string
+}
+```
+
+---
+
+## User Attributes
+
+The following user attributes are automatically set:
+
+### AI Detection Attributes
+- `ai_bot_detected`: boolean
+- `ai_assisted_browser`: boolean
+- `gpt_app_user`: boolean
+- `user_agent`: string
+- `detection_timestamp`: string
+
+### Conditional Attributes
+- `ai_assisted`: true (if AI-assisted browser detected)
+- `gpt_app_user`: true (if running in ChatGPT)
+
+### User Profile Attributes
+Set via `identifyUser()`:
+- `uid`: string (User ID)
+- `u_fn`: string (First Name)
+- `u_em`: string (Email)
+- `u_mb`: string (Mobile)
+
+---
+
+## Event Properties Enhancement
+
+All events automatically include these properties (via `useTracking` hook):
+
+```javascript
+{
+ ai_platform: 'chatgpt' | 'web',
+ is_ai_assisted: boolean,
+ is_gpt_app: boolean,
+ timestamp: string
+}
+```
+
+---
+
+## AI Bot Blocking
+
+Events are automatically blocked if AI bot is detected:
+- `aiDetection.shouldBlockTracking()` returns `true`
+- Event tracking is skipped
+- Log entry shows: "Event blocked (AI Bot detected): {event_name}"
+
+---
+
+## Tracking Flow Example
+
+### Complete Booking Journey:
+
+1. **App Loads**
+ - `app_loaded`
+ - `ai_detection_performed`
+ - `gpt_app_session_start` (if in ChatGPT)
+
+2. **User Searches**
+ - `search_form_viewed`
+ - `search_form_submitted`
+ - `hotel_search`
+ - `hotel_search_results`
+ - `hotel_results_viewed`
+ - `hotel_impression` (for each hotel)
+
+3. **User Views Hotel**
+ - `hotel_card_clicked`
+ - `hotel_viewed`
+ - `booking_flow_started`
+ - `booking_page_viewed`
+
+4. **User Fills Booking Form**
+ - `booking_form_field_changed` (multiple times)
+ - `payment_method_selected`
+
+5. **User Completes Booking**
+ - `booking_started`
+ - `booking_completed`
+ - `conversion`
+
+---
+
+## MoEngage Dashboard Usage
+
+### Key Metrics to Monitor:
+
+1. **Search Metrics**:
+ - `hotel_search` count
+ - Average `results_count` from `hotel_search_results`
+ - Search-to-view conversion rate
+
+2. **Engagement Metrics**:
+ - `hotel_impression` count
+ - `hotel_viewed` count
+ - Click-through rate (CTR)
+
+3. **Conversion Metrics**:
+ - `booking_started` count
+ - `booking_completed` count
+ - Booking completion rate
+ - Revenue from `conversion` events
+
+4. **AI Platform Metrics**:
+ - Events with `is_gpt_app: true`
+ - Events with `is_ai_assisted: true`
+ - Platform comparison (ChatGPT vs Web)
+
+### Segmentation:
+
+Create segments based on:
+- `gpt_app_user == true` (ChatGPT users)
+- `ai_assisted == true` (AI-assisted browser users)
+- `booking_completed` events (Converted users)
+- `destination` property (Geographic segments)
+
+---
+
+## Testing Tracking
+
+1. **Open Browser DevTools** (F12)
+2. **Go to Network Tab**
+3. **Filter by "moengage"**
+4. **Perform actions** in the app
+5. **Verify events** are being sent
+6. **Check MoEngage Dashboard** for events
+
+---
+
+## Troubleshooting
+
+### Events Not Appearing:
+
+1. Check MoEngage SDK initialization
+2. Verify App ID and Data Center
+3. Check browser console for errors
+4. Verify CSP allows MoEngage domains
+5. Check AI bot detection isn't blocking
+
+### Missing Properties:
+
+1. Verify event tracking calls include all properties
+2. Check `useTracking` hook is adding AI detection properties
+3. Verify user identification is set
+
+---
+
+## Best Practices
+
+1. **Always include context**: Add destination, dates, hotel info where relevant
+2. **Track user journey**: Track each step of the booking flow
+3. **Use consistent naming**: Follow event naming conventions
+4. **Include timestamps**: All events include automatic timestamps
+5. **Track conversions**: Always track revenue events for bookings
+6. **Monitor AI detection**: Use AI detection attributes for segmentation
+
+---
+
+For more information, see:
+- [MoEngage Documentation](https://docs.moengage.com/)
+- [ChatGPT Testing Guide](./CHATGPT_TESTING_GUIDE.md)
+- [Implementation Summary](./IMPLEMENTATION_SUMMARY.md)
+
diff --git a/chatgpt-app-sample/QUICKSTART.md b/chatgpt-app-sample/QUICKSTART.md
new file mode 100644
index 00000000..880a97bd
--- /dev/null
+++ b/chatgpt-app-sample/QUICKSTART.md
@@ -0,0 +1,119 @@
+# Quick Start Guide - Next.js
+
+## Prerequisites
+
+- Node.js 18+ (or Node 12 via nvm as per project requirements)
+- npm or yarn
+
+## 5-Minute Setup
+
+### Step 1: Install Dependencies
+
+```bash
+npm install
+```
+
+### Step 2: Configure MoEngage
+
+Create `.env.local` file:
+
+```env
+NEXT_PUBLIC_MOENGAGE_DATACENTER=dc_01
+NEXT_PUBLIC_MOENGAGE_APP_ID=YOUR_MOENGAGE_APP_ID
+```
+
+Or edit `app/page.tsx` directly:
+
+```typescript
+const MOENGAGE_CONFIG = {
+ dataCenter: 'dc_01', // Your Data Center
+ appId: 'YOUR_MOENGAGE_APP_ID', // Your App ID
+ // ...
+};
+```
+
+### Step 3: Run Development Server
+
+```bash
+npm run dev
+```
+
+### Step 4: Open in Browser
+
+Navigate to: `http://localhost:3000`
+
+### Step 5: Test Tracking
+
+1. Wait for "MoEngage SDK Ready ✓" message
+2. Click "Track Page View" - Check logs
+3. Enter user info and click "Identify User"
+4. Click other tracking buttons
+5. Check MoEngage dashboard for events
+
+## For ChatGPT Integration
+
+### Step 1: Build and Deploy
+
+```bash
+npm run build
+```
+
+Deploy to a platform like Vercel, Netlify, or any HTTPS server.
+
+### Step 2: Update Manifest
+
+Edit `public/.well-known/openai-apps.json`:
+- Update `homepage_url` to your domain
+
+### Step 3: Verify Manifest Access
+
+Ensure the file is accessible at:
+```
+https://your-domain.com/.well-known/openai-apps.json
+```
+
+### Step 4: Register with OpenAI
+
+Follow OpenAI's ChatGPT Apps registration process.
+
+## Development Commands
+
+```bash
+npm run dev # Start development server
+npm run build # Build for production
+npm start # Start production server
+npm run lint # Run ESLint
+```
+
+## Project Structure
+
+- `app/` - Next.js App Router pages and layouts
+- `components/` - React components
+- `hooks/` - Custom React hooks
+- `lib/` - Utility functions and SDK wrappers
+- `public/` - Static files including ChatGPT manifest
+
+## Common Issues
+
+**SDK not loading?**
+- Check Data Center and App ID in `.env.local` or `app/page.tsx`
+- Verify internet connection
+- Check browser console
+
+**Build errors?**
+- Clear `.next` folder: `rm -rf .next`
+- Reinstall dependencies: `rm -rf node_modules && npm install`
+- Check Node.js version: `node --version`
+
+**Events not tracking?**
+- Verify SDK initialized (check UI status)
+- Check if AI bot is blocking (see detection section)
+- Ensure user is identified
+
+## Next Steps
+
+- Review `README.md` for detailed documentation
+- Check `INTEGRATION_EXAMPLES.md` for code examples
+- Customize tracking events for your use case
+- Configure MoEngage campaigns
+- Set up user segmentation
diff --git a/chatgpt-app-sample/QUICK_DEPLOY.md b/chatgpt-app-sample/QUICK_DEPLOY.md
new file mode 100644
index 00000000..6effd5ff
--- /dev/null
+++ b/chatgpt-app-sample/QUICK_DEPLOY.md
@@ -0,0 +1,112 @@
+# 🚀 Quick Deployment Steps
+
+Your project is ready! Here are the fastest ways to deploy:
+
+## Method 1: Vercel Dashboard (Recommended - 5 minutes)
+
+### Step 1: Push to GitHub
+```bash
+cd /Users/aman.verma/Desktop/Projects/OPEN_AI_SDK/chatgpt-app-sample
+
+# Add all changes
+git add .
+
+# Commit
+git commit -m "Add hotel booking app with MoEngage integration"
+
+# Push (if you have remote)
+git push origin feat/chatgpt-app-integration
+```
+
+### Step 2: Deploy on Vercel
+1. Go to: **https://vercel.com/new**
+2. Click **"Import Git Repository"**
+3. Select your repository
+4. Configure:
+ - Framework: **Next.js** (auto)
+ - Add Environment Variables:
+ - `NEXT_PUBLIC_MOENGAGE_DATACENTER` = `dc_01`
+ - `NEXT_PUBLIC_MOENGAGE_APP_ID` = `3RADPYNEBZ2MCOJ43EEW5FWV`
+5. Click **"Deploy"**
+6. **Copy your URL** (e.g., `https://hotel-booking-app.vercel.app`)
+
+### Step 3: Update Config Files
+After deployment, update these files with your **actual Vercel URL**:
+
+**File: `public/ai-plugin.json`**
+- Replace `https://your-app.vercel.app` with your actual URL
+
+**File: `public/.well-known/openapi.yaml`**
+- Replace `https://your-app.vercel.app` with your actual URL
+
+Then commit and push:
+```bash
+git add .
+git commit -m "Update deployment URLs"
+git push
+```
+
+Vercel will auto-redeploy!
+
+---
+
+## Method 2: Vercel CLI (If you can login)
+
+### Step 1: Login
+```bash
+vercel login
+```
+
+### Step 2: Deploy
+```bash
+cd /Users/aman.verma/Desktop/Projects/OPEN_AI_SDK/chatgpt-app-sample
+vercel
+```
+
+When prompted:
+- Link to existing? → **N**
+- Project name → Press **Enter**
+- Directory → Press **Enter**
+- Override? → **N**
+
+### Step 3: Add Environment Variables
+1. Go to: https://vercel.com/dashboard
+2. Select your project
+3. **Settings** → **Environment Variables**
+4. Add both variables
+5. **Redeploy**
+
+---
+
+## After Deployment: Create ChatGPT GPT
+
+1. **Go to**: https://platform.openai.com/
+2. **Click**: "GPTs" → "Create"
+3. **Configure**:
+ - Name: `Hotel Booking Assistant`
+ - Instructions: `You are a hotel booking assistant. Help users search and book hotels.`
+4. **Add Widget**:
+ - Widget URL: `https://YOUR-VERCEL-URL.vercel.app`
+5. **Save**
+
+---
+
+## Test in ChatGPT
+
+1. Go to: https://chat.openai.com
+2. Click your name → "My GPTs" → "Hotel Booking Assistant"
+3. Try: `"I want to book a hotel in Paris for next week"`
+
+---
+
+## Verify MoEngage
+
+1. Open DevTools (F12) → Network tab
+2. Filter: `moengage`
+3. Perform actions in app
+4. Check: https://app.moengage.com/
+
+---
+
+**Choose Method 1 if you have GitHub, or Method 2 if you prefer CLI!**
+
diff --git a/chatgpt-app-sample/QUICK_START.md b/chatgpt-app-sample/QUICK_START.md
new file mode 100644
index 00000000..9a263015
--- /dev/null
+++ b/chatgpt-app-sample/QUICK_START.md
@@ -0,0 +1,64 @@
+# Quick Start Guide
+
+## 1. Install Dependencies
+
+```bash
+npm install
+```
+
+## 2. Configure Environment Variables
+
+Create `.env.local` file:
+
+```env
+NEXT_PUBLIC_MOENGAGE_DATACENTER=dc_01
+NEXT_PUBLIC_MOENGAGE_APP_ID=3RADPYNEBZ2MCOJ43EEW5FWV
+```
+
+## 3. Run Development Server
+
+```bash
+npm run dev
+```
+
+Open http://localhost:4000
+
+## 4. Test Locally
+
+1. **Search for Hotels**: Enter a destination, dates, and guests
+2. **View Results**: Browse available hotels
+3. **Complete Booking**: Fill in guest information and complete booking
+4. **Check Tracking**: View tracking logs in the sidebar
+
+## 5. Deploy to Production
+
+### Deploy to Vercel:
+
+```bash
+npm install -g vercel
+vercel
+```
+
+### Update ChatGPT Configuration:
+
+1. Update `public/ai-plugin.json` with your deployment URL
+2. Update `public/.well-known/openapi.yaml` with your deployment URL
+3. Follow the [ChatGPT Testing Guide](./CHATGPT_TESTING_GUIDE.md) for complete setup
+
+## Features
+
+- ✅ Hotel search and booking interface
+- ✅ MoEngage WebSDK integration (staging version)
+- ✅ AI bot detection and blocking
+- ✅ AI-assisted browser detection
+- ✅ GPT app detection
+- ✅ Comprehensive event tracking
+- ✅ User identification
+- ✅ Real-time tracking logs
+
+## Next Steps
+
+- Read [CHATGPT_TESTING_GUIDE.md](./CHATGPT_TESTING_GUIDE.md) for complete ChatGPT integration
+- Check [README.md](./README.md) for project overview
+- Review [DEPLOYMENT_INSTRUCTIONS.md](./DEPLOYMENT_INSTRUCTIONS.md) for deployment details
+
diff --git a/chatgpt-app-sample/QUICK_START_CHATGPT.md b/chatgpt-app-sample/QUICK_START_CHATGPT.md
new file mode 100644
index 00000000..73f0758a
--- /dev/null
+++ b/chatgpt-app-sample/QUICK_START_CHATGPT.md
@@ -0,0 +1,91 @@
+# ⚡ Quick Start: Use in ChatGPT (5 Minutes)
+
+## 🎯 Goal
+Get your hotel booking app working directly in ChatGPT.
+
+---
+
+## Step 1: Deploy (2 minutes)
+
+1. Go to: **https://vercel.com/new**
+2. Click **"Import Git Repository"**
+3. Select: `moengage/webSDK-sample`
+4. Branch: `feat/chatgpt-app-integration`
+5. **Root Directory**: `chatgpt-app-sample` ⚠️ **IMPORTANT**
+6. Add Environment Variables:
+ - `NEXT_PUBLIC_MOENGAGE_DATACENTER` = `dc_01`
+ - `NEXT_PUBLIC_MOENGAGE_APP_ID` = `3RADPYNEBZ2MCOJ43EEW5FWV`
+7. Click **"Deploy"**
+8. **Copy your URL**: `https://your-app.vercel.app`
+
+---
+
+## Step 2: Update URLs (1 minute)
+
+Update these files with your Vercel URL:
+
+**File: `public/ai-plugin.json`**
+```json
+{
+ "api": {
+ "url": "https://YOUR-URL.vercel.app/.well-known/openapi.yaml"
+ }
+}
+```
+
+**File: `public/.well-known/openapi.yaml`**
+```yaml
+servers:
+ - url: https://YOUR-URL.vercel.app
+```
+
+Then:
+```bash
+git add public/
+git commit -m "Update URLs"
+git push
+```
+
+---
+
+## Step 3: Create ChatGPT GPT (1 minute)
+
+1. Go to: **https://platform.openai.com/**
+2. Click **"GPTs"** → **"Create"**
+3. Name: `Hotel Booking Assistant`
+4. **Widget URL**: `https://YOUR-URL.vercel.app`
+5. **Widget CSP**:
+ ```json
+ {
+ "openai/widgetCSP": {
+ "connect_domains": ["https://*.moengage.com"],
+ "resource_domains": ["https://js.moengage.com", "https://cdn.moengage.com"]
+ }
+ }
+ ```
+6. Click **"Save"**
+
+---
+
+## Step 4: Use It! (1 minute)
+
+1. Go to: **https://chat.openai.com**
+2. Click your name → **"My GPTs"**
+3. Select **"Hotel Booking Assistant"**
+4. Try: `"I want to book a hotel in Paris"`
+
+**Done!** 🎉
+
+---
+
+## ✅ Verify
+
+- Widget appears in ChatGPT ✅
+- Can search hotels ✅
+- Can complete booking ✅
+- MoEngage tracking works ✅
+
+---
+
+**That's it! Your app is now live in ChatGPT!** 🚀
+
diff --git a/chatgpt-app-sample/README.md b/chatgpt-app-sample/README.md
new file mode 100644
index 00000000..4d4e9200
--- /dev/null
+++ b/chatgpt-app-sample/README.md
@@ -0,0 +1,75 @@
+# Booking.com-like Hotel Booking App with MoEngage
+
+A Next.js hotel booking application (similar to Booking.com) demonstrating MoEngage WebSDK integration with ChatGPT Apps. This app includes comprehensive tracking, AI detection, and user engagement capabilities.
+
+## Features
+
+- ✅ **Booking.com-like Interface** - Professional hotel booking UI
+- ✅ **Next.js 14** - Modern React framework with App Router
+- ✅ **TypeScript** - Full type safety
+- ✅ **MoEngage WebSDK Integration** - Full tracking and analytics (Staging SDK v5.02.45)
+- ✅ **ChatGPT Apps SDK Integration** - Compatible with OpenAI's ChatGPT Apps platform
+- ✅ **AI Bot Detection** - Automatically detects and blocks AI bot traffic
+- ✅ **AI-Assisted Browser Detection** - Identifies users on AI-assisted browsers
+- ✅ **GPT App Detection** - Detects when app is running within ChatGPT
+- ✅ **Comprehensive Event Tracking** - Tracks hotel searches, views, and bookings
+- ✅ **User Identification** - Track users across sessions
+- ✅ **Real-time Tracking Logs** - Monitor all events in real-time
+
+## Quick Start
+
+1. **Install dependencies:**
+ ```bash
+ npm install
+ ```
+
+2. **Configure MoEngage:**
+ Create `.env.local`:
+ ```
+ NEXT_PUBLIC_MOENGAGE_DATACENTER=dc_01
+ NEXT_PUBLIC_MOENGAGE_APP_ID=3RADPYNEBZ2MCOJ43EEW5FWV
+ ```
+
+3. **Run development server:**
+ ```bash
+ npm run dev
+ ```
+
+4. **Open:** http://localhost:4000
+
+## Testing in ChatGPT
+
+**📖 Complete Step-by-Step Guide**: See [CHATGPT_TESTING_GUIDE.md](./CHATGPT_TESTING_GUIDE.md) for detailed instructions on:
+- Deploying your app
+- Creating a ChatGPT GPT
+- Configuring widgets and CSP
+- Testing all scenarios
+- Verifying MoEngage tracking
+
+## Documentation
+
+- [Quick Start Guide](./QUICK_START.md) - Get started quickly
+- [ChatGPT Testing Guide](./CHATGPT_TESTING_GUIDE.md) - **Complete guide for testing in ChatGPT**
+- [MoEngage Tracking Guide](./MOENGAGE_TRACKING.md) - **Complete event tracking documentation**
+- [Deployment Instructions](./DEPLOYMENT_INSTRUCTIONS.md) - Production deployment
+- [Integration Examples](./INTEGRATION_EXAMPLES.md) - Code examples
+
+## Project Structure
+
+```
+chatgpt-app-sample/
+├── app/ # Next.js App Router
+├── components/ # React components
+├── hooks/ # Custom React hooks
+├── lib/ # Utility functions
+├── public/ # Static files
+└── package.json
+```
+
+## For More Details
+
+See the individual documentation files for:
+- Local testing instructions
+- ChatGPT integration steps
+- Deployment to Vercel
+- Code examples and use cases
diff --git a/chatgpt-app-sample/TESTING_GUIDE.md b/chatgpt-app-sample/TESTING_GUIDE.md
new file mode 100644
index 00000000..2d2a38ab
--- /dev/null
+++ b/chatgpt-app-sample/TESTING_GUIDE.md
@@ -0,0 +1,476 @@
+# Testing Guide
+
+Complete guide for testing the MoEngage Sample App locally and in ChatGPT.
+
+## Part 1: Local Testing
+
+### Prerequisites
+
+- Node.js 18+ installed (or Node 12 via nvm as per project requirements)
+- npm or yarn installed
+- MoEngage account with App ID and Data Center
+- A modern web browser (Chrome, Firefox, Safari, Edge)
+
+### Step 1: Install Dependencies
+
+```bash
+cd /Users/aman.verma/Desktop/Projects/OPEN_AI_SDK
+npm install
+```
+
+Expected output:
+```
+added 200+ packages in 30s
+```
+
+### Step 2: Configure MoEngage
+
+**Option A: Using Environment Variables (Recommended)**
+
+1. Create `.env.local` file in the root directory:
+```bash
+touch .env.local
+```
+
+2. Add your MoEngage credentials:
+```env
+NEXT_PUBLIC_MOENGAGE_DATACENTER=dc_01
+NEXT_PUBLIC_MOENGAGE_APP_ID=YOUR_ACTUAL_APP_ID
+```
+
+**Option B: Direct Configuration**
+
+Edit `app/page.tsx` and update the `MOENGAGE_CONFIG` object:
+
+```typescript
+const MOENGAGE_CONFIG = {
+ dataCenter: 'dc_01', // Replace with your Data Center
+ appId: 'YOUR_ACTUAL_APP_ID', // Replace with your App ID
+ sdkVersion: '2',
+ debugLogs: 1,
+};
+```
+
+**How to Get Your MoEngage Credentials:**
+
+1. Log in to your MoEngage dashboard: https://app.moengage.com
+2. Navigate to **Settings** → **Apps** → **Web**
+3. Copy your **App ID** (also called Workspace ID)
+4. Note your **Data Center** (usually `dc_01`, `dc_02`, etc.)
+ - You can find this in the SDK integration code provided by MoEngage
+ - Or check the URL pattern: `https://api-XX.moengage.com` where XX is your data center number
+
+### Step 3: Start Development Server
+
+```bash
+npm run dev
+```
+
+Expected output:
+```
+▲ Next.js 14.0.0
+- Local: http://localhost:3000
+- Ready in 2.5s
+```
+
+### Step 4: Open in Browser
+
+1. Open your browser
+2. Navigate to: `http://localhost:3000`
+3. You should see the MoEngage Sample App interface
+
+### Step 5: Verify MoEngage SDK Initialization
+
+1. **Check the UI:**
+ - Look for "MoEngage SDK Ready ✓" message at the top
+ - If you see "Initializing MoEngage SDK...", wait a few seconds
+
+2. **Check Browser Console:**
+ - Open Developer Tools (F12 or Cmd+Option+I on Mac)
+ - Go to Console tab
+ - You should see: `MoEngage Web SDK initialised` or similar messages
+ - No red error messages related to MoEngage
+
+3. **Check Network Tab:**
+ - Go to Network tab in Developer Tools
+ - Filter by "moengage"
+ - You should see requests to MoEngage CDN and API endpoints
+ - Status should be 200 (success)
+
+### Step 6: Test User Identification
+
+1. Fill in the User Identification form:
+ - **User ID:** `test_user_123`
+ - **Name:** `Test User`
+ - **Email:** `test@example.com`
+ - **Mobile:** `1234567890`
+
+2. Click **"Identify User"** button
+
+3. **Verify:**
+ - Check the Tracking Logs section - should show "User identified: test_user_123"
+ - Check browser console - should see MoEngage API calls
+ - Check MoEngage dashboard → Users → Search for `test_user_123`
+
+### Step 7: Test Event Tracking
+
+1. **Test Pre-configured Events:**
+ - Click **"Track Page View"** - Check logs show success
+ - Click **"Track Button Click"** - Check logs
+ - Click **"Track Product View"** - Check logs
+ - Click **"Track Add to Cart"** - Check logs
+ - Click **"Track Purchase"** - Check logs
+ - Click **"Track Search"** - Check logs
+
+2. **Test Custom Event:**
+ - Enter Event Name: `custom_test_event`
+ - Enter Event Properties: `{"test_key": "test_value", "number": 123}`
+ - Click **"Track Custom Event"**
+ - Verify in logs and MoEngage dashboard
+
+3. **Verify in MoEngage Dashboard:**
+ - Go to MoEngage Dashboard → Analytics → Events
+ - You should see all tracked events
+ - Click on an event to see properties
+
+### Step 8: Test AI Detection
+
+1. **Check AI Detection Section:**
+ - Should automatically show detection results on page load
+ - **User Agent:** Should show your browser's user agent
+ - **AI Bot Detected:** Should show "No" (unless you're using a bot)
+ - **AI-Assisted Browser:** May show "Yes" if using Arc, etc.
+ - **GPT App User:** Should show "No" (you're testing locally)
+
+2. **Test Refresh:**
+ - Click **"Refresh Detection"** button
+ - Results should update
+
+3. **Verify in MoEngage:**
+ - Check user attributes in MoEngage dashboard
+ - Should see: `ai_bot_detected`, `ai_assisted_browser`, `gpt_app_user` attributes
+
+### Step 9: Test Session Management
+
+1. **Destroy Session:**
+ - Click **"Destroy Session"** button
+ - Check logs for confirmation
+ - Verify in MoEngage dashboard
+
+2. **Update User ID:**
+ - Click **"Update User ID"** button
+ - Enter new ID: `test_user_456`
+ - Check logs for confirmation
+
+### Step 10: Verify Tracking Logs
+
+1. All actions should appear in the **Tracking Logs** section
+2. Logs should show:
+ - Timestamp
+ - Event/action description
+ - Color coding (green for success, red for errors, blue for info)
+
+### Step 11: Test AI Bot Detection (Optional)
+
+To test bot detection blocking:
+
+1. Open browser console
+2. Temporarily modify user agent:
+ ```javascript
+ Object.defineProperty(navigator, 'userAgent', {
+ get: () => 'Mozilla/5.0 (compatible; GPTBot/1.0; +https://openai.com/gptbot)'
+ });
+ ```
+3. Refresh the page
+4. Try tracking an event
+5. Should see "Event blocked (AI Bot detected)" in logs
+6. Events should NOT appear in MoEngage dashboard
+
+### Troubleshooting Local Testing
+
+**Issue: SDK not loading**
+- ✅ Check Data Center and App ID are correct
+- ✅ Check internet connection
+- ✅ Check browser console for errors
+- ✅ Verify MoEngage CDN is accessible
+
+**Issue: Events not appearing in MoEngage**
+- ✅ Wait 1-2 minutes (events may be delayed)
+- ✅ Check MoEngage dashboard → Settings → Data Pipeline
+- ✅ Verify App ID is correct
+- ✅ Check browser console for API errors
+
+**Issue: Build errors**
+- ✅ Clear `.next` folder: `rm -rf .next`
+- ✅ Reinstall dependencies: `rm -rf node_modules && npm install`
+- ✅ Check Node.js version: `node --version` (should be 18+)
+
+---
+
+## Part 2: Testing in ChatGPT
+
+### Prerequisites
+
+- Completed local testing successfully
+- HTTPS server/hosting (required for ChatGPT Apps)
+- OpenAI account with ChatGPT Apps access
+- Domain name (or use a hosting service like Vercel)
+
+### Step 1: Build the Application
+
+```bash
+npm run build
+```
+
+Expected output:
+```
+✓ Compiled successfully
+✓ Linting
+✓ Collecting page data
+✓ Generating static pages
+```
+
+### Step 2: Deploy to HTTPS Server
+
+**Option A: Deploy to Vercel (Recommended - Free & Easy)**
+
+1. **Install Vercel CLI:**
+ ```bash
+ npm install -g vercel
+ ```
+
+2. **Login to Vercel:**
+ ```bash
+ vercel login
+ ```
+
+3. **Deploy:**
+ ```bash
+ vercel
+ ```
+ - Follow prompts
+ - Choose production deployment
+ - Note the deployment URL (e.g., `https://your-app.vercel.app`)
+
+4. **Set Environment Variables in Vercel:**
+ - Go to Vercel Dashboard → Your Project → Settings → Environment Variables
+ - Add:
+ - `NEXT_PUBLIC_MOENGAGE_DATACENTER` = `dc_01`
+ - `NEXT_PUBLIC_MOENGAGE_APP_ID` = `YOUR_APP_ID`
+ - Redeploy if needed
+
+**Option B: Deploy to Netlify**
+
+1. **Install Netlify CLI:**
+ ```bash
+ npm install -g netlify-cli
+ ```
+
+2. **Build and Deploy:**
+ ```bash
+ npm run build
+ netlify deploy --prod
+ ```
+
+3. **Set Environment Variables:**
+ - Go to Netlify Dashboard → Site Settings → Environment Variables
+ - Add your MoEngage credentials
+
+**Option C: Deploy to Your Own Server**
+
+1. Build the app: `npm run build`
+2. Copy `.next`, `public`, `package.json`, `node_modules` to your server
+3. Install dependencies: `npm install --production`
+4. Start server: `npm start`
+5. Ensure HTTPS is configured (use Let's Encrypt or similar)
+
+### Step 3: Update ChatGPT App Manifest
+
+1. **Edit `public/.well-known/openai-apps.json`:**
+
+ ```json
+ {
+ "name": "MoEngage Sample App",
+ "description": "Sample application with MoEngage WebSDK integration",
+ "version": "1.0.0",
+ "author": "MoEngage",
+ "homepage_url": "https://your-deployed-url.com",
+ ...
+ }
+ ```
+
+ Replace `https://your-deployed-url.com` with your actual deployment URL.
+
+2. **Verify Manifest is Accessible:**
+ - Open: `https://your-deployed-url.com/.well-known/openai-apps.json`
+ - Should see the JSON file in browser
+ - Check that `Content-Type` is `application/json`
+
+### Step 4: Register App with OpenAI
+
+1. **Access ChatGPT Apps Platform:**
+ - Go to: https://platform.openai.com
+ - Navigate to **Apps** section (or check OpenAI documentation for current URL)
+
+2. **Create New App:**
+ - Click "Create App" or "New App"
+ - Fill in app details:
+ - **Name:** MoEngage Sample App
+ - **Description:** Sample app with MoEngage tracking
+ - **Manifest URL:** `https://your-deployed-url.com/.well-known/openai-apps.json`
+
+3. **Configure App Settings:**
+ - Set app permissions (user_data, analytics)
+ - Review CSP settings (should match your manifest)
+ - Save configuration
+
+4. **Get App ID/Token:**
+ - Note your app's unique identifier
+ - May need this for advanced configurations
+
+### Step 5: Test in ChatGPT
+
+1. **Open ChatGPT:**
+ - Go to: https://chat.openai.com
+ - Log in to your account
+
+2. **Access Your App:**
+ - Look for your app in the ChatGPT interface
+ - May be in a sidebar, menu, or accessible via command
+ - Or use the app URL directly if provided by OpenAI
+
+3. **Verify App Loads:**
+ - App should load within ChatGPT interface
+ - Should see "MoEngage Sample App" interface
+ - Check for "MoEngage SDK Ready ✓" message
+
+### Step 6: Test GPT App Detection
+
+1. **Check AI Detection Section:**
+ - **GPT App User:** Should now show **"Yes"** ✅
+ - This confirms the app is running in ChatGPT environment
+
+2. **Verify in Logs:**
+ - Should see `gpt_app_session_start` event in logs
+ - Should see `chatgpt_app_initialized` event
+
+3. **Check MoEngage Dashboard:**
+ - User attributes should show `gpt_app_user: true`
+ - Events should have `ai_platform: "chatgpt"`
+
+### Step 7: Test Tracking in ChatGPT
+
+1. **Test User Identification:**
+ - Fill in user details
+ - Click "Identify User"
+ - Verify in MoEngage dashboard
+ - Check that `gpt_app_user: true` attribute is set
+
+2. **Test Events:**
+ - Track various events
+ - Verify they appear in MoEngage
+ - Check that events have `ai_platform: "chatgpt"` property
+
+3. **Test ChatGPT Actions:**
+ - If your app receives actions from ChatGPT, they should be tracked
+ - Check logs for `chatgpt_action` events
+
+### Step 8: Verify MoEngage Integration
+
+1. **Check MoEngage Dashboard:**
+ - Go to Users → Search for your test user
+ - Verify attributes:
+ - `gpt_app_user: true`
+ - `ai_platform: "chatgpt"` (in events)
+ - Other user attributes
+
+2. **Check Events:**
+ - Go to Analytics → Events
+ - Filter by your test user
+ - Verify all events are tracked
+ - Check event properties include `ai_platform: "chatgpt"`
+
+3. **Check Segments:**
+ - Create a segment: `gpt_app_user == true`
+ - Should include your test user
+
+### Troubleshooting ChatGPT Integration
+
+**Issue: App not loading in ChatGPT**
+- ✅ Verify HTTPS is enabled
+- ✅ Check manifest URL is accessible
+- ✅ Verify CSP configuration in manifest
+- ✅ Check OpenAI app registration status
+- ✅ Review OpenAI console for errors
+
+**Issue: GPT App detection not working**
+- ✅ Check if app is actually running in ChatGPT (not just iframe)
+- ✅ Verify `window.parent` detection logic
+- ✅ Check browser console for errors
+
+**Issue: Events not tracking in ChatGPT**
+- ✅ Verify MoEngage SDK loads (check console)
+- ✅ Check CSP allows MoEngage domains
+- ✅ Verify network requests to MoEngage API
+- ✅ Check MoEngage dashboard for events (may be delayed)
+
+**Issue: CSP errors**
+- ✅ Verify all MoEngage domains are in manifest
+- ✅ Check your data center matches the domains
+- ✅ Review browser console for CSP violations
+
+### Step 9: Advanced Testing
+
+1. **Test Multiple Users:**
+ - Identify different users
+ - Track events for each
+ - Verify segmentation works
+
+2. **Test Campaigns:**
+ - Create MoEngage campaigns targeting `gpt_app_user == true`
+ - Verify campaigns appear in app
+ - Test campaign interactions
+
+3. **Test Analytics:**
+ - Create funnels in MoEngage
+ - Build reports with GPT app events
+ - Verify attribution works correctly
+
+### Checklist
+
+**Local Testing:**
+- [ ] Dependencies installed
+- [ ] MoEngage configured
+- [ ] App runs on localhost:3000
+- [ ] SDK initializes successfully
+- [ ] User identification works
+- [ ] Events track correctly
+- [ ] AI detection works
+- [ ] Logs display properly
+- [ ] Events appear in MoEngage dashboard
+
+**ChatGPT Testing:**
+- [ ] App built successfully
+- [ ] Deployed to HTTPS server
+- [ ] Manifest accessible
+- [ ] App registered with OpenAI
+- [ ] App loads in ChatGPT
+- [ ] GPT app detection works
+- [ ] Tracking works in ChatGPT
+- [ ] Events have correct properties
+- [ ] User attributes set correctly
+- [ ] MoEngage dashboard shows GPT app users
+
+## Support
+
+If you encounter issues:
+
+1. Check browser console for errors
+2. Review MoEngage dashboard for data
+3. Verify all configuration steps
+4. Check OpenAI/OpenAI Apps documentation
+5. Review this guide's troubleshooting sections
+
+For MoEngage-specific issues, contact MoEngage support.
+For ChatGPT Apps issues, check OpenAI documentation or support.
+
diff --git a/chatgpt-app-sample/TESTING_STEPS.md b/chatgpt-app-sample/TESTING_STEPS.md
new file mode 100644
index 00000000..d6166dd8
--- /dev/null
+++ b/chatgpt-app-sample/TESTING_STEPS.md
@@ -0,0 +1,307 @@
+# Step-by-Step ChatGPT Testing Guide
+
+Follow these steps to test your hotel booking app in ChatGPT.
+
+## Step 1: Deploy Your App to Vercel
+
+### Option A: Using Vercel CLI (Recommended)
+
+1. **Install Vercel CLI** (if not installed):
+ ```bash
+ npm install -g vercel
+ ```
+
+2. **Login to Vercel**:
+ ```bash
+ vercel login
+ ```
+
+3. **Deploy from project directory**:
+ ```bash
+ cd /Users/aman.verma/Desktop/Projects/OPEN_AI_SDK/chatgpt-app-sample
+ vercel
+ ```
+
+4. **Follow prompts**:
+ - Link to existing project? **N** (for first time)
+ - Project name: **hotel-booking-app** (or your choice)
+ - Directory: **./** (current directory)
+ - Override settings? **N**
+
+5. **Note your deployment URL**:
+ - You'll get something like: `https://hotel-booking-app-xyz.vercel.app`
+ - **IMPORTANT**: Copy this URL - you'll need it!
+
+6. **Add Environment Variables in Vercel Dashboard**:
+ - Go to: https://vercel.com/dashboard
+ - Select your project
+ - Go to Settings → Environment Variables
+ - Add:
+ - `NEXT_PUBLIC_MOENGAGE_DATACENTER` = `dc_01`
+ - `NEXT_PUBLIC_MOENGAGE_APP_ID` = `3RADPYNEBZ2MCOJ43EEW5FWV`
+ - Click "Save"
+ - Redeploy: Go to Deployments → Click "..." → "Redeploy"
+
+### Option B: Using Vercel Dashboard
+
+1. Go to https://vercel.com/new
+2. Import your GitHub repository (or drag & drop your project folder)
+3. Configure:
+ - Framework Preset: **Next.js**
+ - Root Directory: **./**
+4. Add Environment Variables:
+ - `NEXT_PUBLIC_MOENGAGE_DATACENTER` = `dc_01`
+ - `NEXT_PUBLIC_MOENGAGE_APP_ID` = `3RADPYNEBZ2MCOJ43EEW5FWV`
+5. Click "Deploy"
+6. Wait for deployment to complete
+7. Copy your deployment URL
+
+---
+
+## Step 2: Update Configuration Files
+
+After deployment, update these files with your actual deployment URL:
+
+### 2.1 Update `public/ai-plugin.json`
+
+Replace `https://your-app.vercel.app` with your actual URL:
+
+```json
+{
+ "api": {
+ "url": "https://YOUR-ACTUAL-URL.vercel.app/.well-known/openapi.yaml"
+ },
+ "logo_url": "https://YOUR-ACTUAL-URL.vercel.app/logo.png",
+ "legal_info_url": "https://YOUR-ACTUAL-URL.vercel.app/legal"
+}
+```
+
+### 2.2 Update `public/.well-known/openapi.yaml`
+
+Replace `https://your-app.vercel.app` with your actual URL:
+
+```yaml
+servers:
+ - url: https://YOUR-ACTUAL-URL.vercel.app
+```
+
+### 2.3 Redeploy After Changes
+
+```bash
+vercel --prod
+```
+
+Or push to GitHub if using GitHub integration.
+
+---
+
+## Step 3: Create ChatGPT GPT
+
+1. **Go to OpenAI Platform**:
+ - Visit: https://platform.openai.com/
+ - Login with your ChatGPT Plus account
+
+2. **Navigate to GPTs**:
+ - Click "GPTs" in the left sidebar
+ - Click "Create" or "+" button
+
+3. **Configure GPT**:
+
+ **Configure Tab:**
+ - **Name**: `Hotel Booking Assistant`
+ - **Description**: `Helps users search and book hotels with real-time availability`
+ - **Instructions**:
+ ```
+ You are a helpful hotel booking assistant. When users ask about hotels,
+ help them search for available hotels by destination, dates, and number of guests.
+ Use the hotel booking widget to show them options and help them complete bookings.
+ ```
+
+4. **Add Widget**:
+ - Scroll down to "Additional Settings" or "Widget" section
+ - **Widget URL**: `https://YOUR-ACTUAL-URL.vercel.app`
+ - **Widget CSP** (if available): Add this JSON:
+ ```json
+ {
+ "openai/widgetCSP": {
+ "connect_domains": [
+ "https://*.moengage.com",
+ "https://api.moengage.com"
+ ],
+ "resource_domains": [
+ "https://js.moengage.com",
+ "https://cdn.moengage.com",
+ "https://sdk-0X-moengage.com"
+ ]
+ }
+ }
+ ```
+
+5. **Save GPT**:
+ - Click "Save" button (top right)
+ - Choose visibility: **"Only me"** (for testing) or **"Anyone with a link"**
+ - Click "Confirm"
+
+---
+
+## Step 4: Test in ChatGPT
+
+1. **Open ChatGPT**:
+ - Go to: https://chat.openai.com
+ - Make sure you're logged in with ChatGPT Plus
+
+2. **Access Your GPT**:
+ - Click on your profile/name (top right)
+ - Click "My GPTs"
+ - Find and click "Hotel Booking Assistant"
+
+3. **Start Testing**:
+
+ **Test 1: Basic Search**
+ ```
+ "I want to book a hotel in Paris for next week"
+ ```
+ - Expected: Widget should appear with hotel search form
+
+ **Test 2: Specific Search**
+ ```
+ "Find hotels in New York from December 20 to December 25 for 2 guests"
+ ```
+ - Expected: Search form should appear with pre-filled dates
+
+ **Test 3: View Hotels**
+ - Click "Search" in the widget
+ - Expected: Hotel results should appear
+
+ **Test 4: Select Hotel**
+ - Click on a hotel card
+ - Expected: Booking form should appear
+
+ **Test 5: Complete Booking**
+ - Fill in guest information
+ - Select payment method
+ - Click "Complete Booking"
+ - Expected: Booking confirmation
+
+---
+
+## Step 5: Verify MoEngage Tracking
+
+1. **Open Browser DevTools**:
+ - Press `F12` or `Cmd+Option+I` (Mac)
+ - Go to "Network" tab
+ - Filter by: `moengage`
+
+2. **Perform Actions**:
+ - Search for hotels
+ - View hotel details
+ - Start booking
+ - Complete booking
+
+3. **Check Network Requests**:
+ - You should see requests to `*.moengage.com`
+ - Check request payloads contain event data
+
+4. **Check MoEngage Dashboard**:
+ - Login to: https://app.moengage.com/
+ - Go to "Analytics" → "Events"
+ - Look for events:
+ - `app_loaded`
+ - `hotel_search`
+ - `hotel_viewed`
+ - `booking_started`
+ - `booking_completed`
+ - `gpt_app_session_start` (if in ChatGPT)
+
+5. **Verify User Attributes**:
+ - Go to "Users" section
+ - Check for attributes:
+ - `gpt_app_user: true`
+ - `ai_platform: "chatgpt"`
+ - `is_gpt_app: true`
+
+---
+
+## Step 6: Troubleshooting
+
+### Widget Not Showing?
+
+1. **Check Widget URL**: Make sure it's correct in GPT settings
+2. **Check CSP**: Verify CSP headers in browser console
+3. **Check HTTPS**: Ensure your app is on HTTPS
+4. **Check Console**: Look for errors in browser DevTools
+
+### MoEngage Not Tracking?
+
+1. **Check SDK Loading**:
+ - Network tab → Filter "moengage"
+ - Look for `sdk.js` file loading
+ - Check for errors (red requests)
+
+2. **Check App ID**:
+ - Verify `NEXT_PUBLIC_MOENGAGE_APP_ID` is correct
+ - Check environment variables in Vercel
+
+3. **Check CSP**:
+ - Browser console → Look for CSP errors
+ - Verify `js.moengage.com` is allowed
+
+4. **Check AI Bot Detection**:
+ - If bot detected, events will be blocked
+ - Check tracking logs in sidebar
+
+### Events Not in Dashboard?
+
+1. **Wait a few minutes**: Events may take 1-2 minutes to appear
+2. **Check Filters**: Make sure no date/event filters are applied
+3. **Check App ID**: Verify you're looking at the correct app
+4. **Check Debug Logs**: Enable debug logs in `.env.local`:
+ ```
+ NEXT_PUBLIC_MOENGAGE_DEBUG_LOGS=1
+ ```
+
+---
+
+## Quick Commands Reference
+
+```bash
+# Install dependencies
+npm install
+
+# Run locally
+npm run dev
+
+# Build for production
+npm run build
+
+# Deploy to Vercel
+vercel
+
+# Deploy to production
+vercel --prod
+
+# Check deployment
+vercel ls
+```
+
+---
+
+## Next Steps After Testing
+
+1. ✅ Verify all events are tracking
+2. ✅ Test user identification
+3. ✅ Check AI detection attributes
+4. ✅ Monitor MoEngage dashboard
+5. ✅ Create segments for GPT app users
+6. ✅ Set up alerts for conversions
+
+---
+
+## Support
+
+- **MoEngage Docs**: https://docs.moengage.com/
+- **OpenAI GPTs**: https://platform.openai.com/docs/guides/gpts
+- **Vercel Docs**: https://vercel.com/docs
+
+Good luck! 🚀
+
diff --git a/chatgpt-app-sample/app/globals.css b/chatgpt-app-sample/app/globals.css
new file mode 100644
index 00000000..a5be6c20
--- /dev/null
+++ b/chatgpt-app-sample/app/globals.css
@@ -0,0 +1,33 @@
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+body {
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
+ background: #f5f5f5;
+ color: #333;
+ line-height: 1.6;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+a {
+ color: #003580;
+ text-decoration: none;
+}
+
+a:hover {
+ text-decoration: underline;
+}
+
+button {
+ font-family: inherit;
+}
+
+input,
+textarea,
+select {
+ font-family: inherit;
+}
diff --git a/chatgpt-app-sample/app/layout.tsx b/chatgpt-app-sample/app/layout.tsx
new file mode 100644
index 00000000..0f1e53d6
--- /dev/null
+++ b/chatgpt-app-sample/app/layout.tsx
@@ -0,0 +1,30 @@
+import type { Metadata } from 'next';
+import './globals.css';
+
+export const metadata: Metadata = {
+ title: 'MoEngage Sample App - ChatGPT Integration',
+ description: 'Sample application with MoEngage WebSDK integration for ChatGPT Apps',
+};
+
+export default function RootLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return (
+
+
+
+
+
+ {children}
+
+ );
+}
+
diff --git a/chatgpt-app-sample/app/page.module.css b/chatgpt-app-sample/app/page.module.css
new file mode 100644
index 00000000..1cb817a7
--- /dev/null
+++ b/chatgpt-app-sample/app/page.module.css
@@ -0,0 +1,85 @@
+.app {
+ min-height: 100vh;
+ background: #f5f5f5;
+ display: grid;
+ grid-template-columns: 1fr 350px;
+ grid-template-rows: auto 1fr;
+ grid-template-areas:
+ 'header header'
+ 'main sidebar';
+}
+
+.header {
+ grid-area: header;
+ background: #003580;
+ color: white;
+ padding: 1rem 2rem;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.headerContent {
+ max-width: 1400px;
+ margin: 0 auto;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.logo {
+ font-size: 1.8rem;
+ font-weight: bold;
+ margin: 0;
+ color: white;
+}
+
+.headerStatus {
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+}
+
+.statusBadge {
+ background: #ff6b6b;
+ color: white;
+ padding: 0.4rem 0.8rem;
+ border-radius: 4px;
+ font-size: 0.85rem;
+}
+
+.statusBadgeReady {
+ background: #51cf66;
+ color: white;
+ padding: 0.4rem 0.8rem;
+ border-radius: 4px;
+ font-size: 0.85rem;
+}
+
+.main {
+ grid-area: main;
+ padding: 2rem;
+ overflow-y: auto;
+}
+
+.sidebar {
+ grid-area: sidebar;
+ background: white;
+ border-left: 1px solid #e0e0e0;
+ padding: 1.5rem;
+ overflow-y: auto;
+}
+
+@media (max-width: 1024px) {
+ .app {
+ grid-template-columns: 1fr;
+ grid-template-areas:
+ 'header'
+ 'main'
+ 'sidebar';
+ }
+
+ .sidebar {
+ border-left: none;
+ border-top: 1px solid #e0e0e0;
+ }
+}
+
diff --git a/chatgpt-app-sample/app/page.tsx b/chatgpt-app-sample/app/page.tsx
new file mode 100644
index 00000000..0acb901f
--- /dev/null
+++ b/chatgpt-app-sample/app/page.tsx
@@ -0,0 +1,266 @@
+'use client';
+
+import { useEffect, useState, useCallback } from 'react';
+import { useMoEngage } from '@/hooks/useMoEngage';
+import { useTracking, LogEntry } from '@/hooks/useTracking';
+import { initializeChatGPTApps } from '@/lib/chatgpt-apps';
+import { trackEvent } from '@/lib/moengage';
+import HotelSearch from '@/components/HotelSearch';
+import HotelResults from '@/components/HotelResults';
+import HotelBooking from '@/components/HotelBooking';
+import UserProfile from '@/components/UserProfile';
+import TrackingLogs from '@/components/TrackingLogs';
+import styles from './page.module.css';
+
+const MOENGAGE_CONFIG = {
+ dataCenter: process.env.NEXT_PUBLIC_MOENGAGE_DATACENTER || 'dc_01',
+ appId: process.env.NEXT_PUBLIC_MOENGAGE_APP_ID || '3RADPYNEBZ2MCOJ43EEW5FWV',
+ sdkVersion: '2',
+ debugLogs: 0,
+};
+
+export interface Hotel {
+ id: string;
+ name: string;
+ location: string;
+ rating: number;
+ price: number;
+ image: string;
+ amenities: string[];
+ description: string;
+}
+
+export default function Home() {
+ const [logs, setLogs] = useState([]);
+ const [searchParams, setSearchParams] = useState<{
+ destination: string;
+ checkIn: string;
+ checkOut: string;
+ guests: number;
+ } | null>(null);
+ const [hotels, setHotels] = useState([]);
+ const [selectedHotel, setSelectedHotel] = useState(null);
+ const [showBooking, setShowBooking] = useState(false);
+ const { isReady } = useMoEngage(MOENGAGE_CONFIG);
+
+ const handleLog = useCallback((log: LogEntry) => {
+ setLogs((prev) => [...prev, log]);
+ }, []);
+
+ const { track } = useTracking(handleLog);
+
+ useEffect(() => {
+ if (isReady) {
+ track('app_loaded', {
+ load_time: typeof window !== 'undefined' ? performance.now() : 0,
+ page: 'home',
+ });
+
+ const chatGPTApp = initializeChatGPTApps((action) => {
+ track('chatgpt_action', {
+ action_type: action.type,
+ action_data: JSON.stringify(action.data || {}),
+ });
+ });
+
+ if (chatGPTApp) {
+ track('chatgpt_app_initialized', {});
+ }
+ }
+ }, [isReady, track]);
+
+ useEffect(() => {
+ if (typeof window === 'undefined') return;
+
+ const handleBeforeUnload = () => {
+ trackEvent('session_end', {
+ session_duration: performance.now(),
+ timestamp: new Date().toISOString(),
+ });
+ };
+
+ window.addEventListener('beforeunload', handleBeforeUnload);
+ return () => window.removeEventListener('beforeunload', handleBeforeUnload);
+ }, [track]);
+
+ const handleSearch = (params: { destination: string; checkIn: string; checkOut: string; guests: number }) => {
+ setSearchParams(params);
+ track('hotel_search', {
+ destination: params.destination,
+ check_in: params.checkIn,
+ check_out: params.checkOut,
+ guests: params.guests,
+ });
+
+ const mockHotels: Hotel[] = [
+ {
+ id: '1',
+ name: 'Grand Plaza Hotel',
+ location: params.destination,
+ rating: 4.5,
+ price: 129,
+ image: 'https://images.unsplash.com/photo-1566073771259-6a8506099945?w=800',
+ amenities: ['Free WiFi', 'Pool', 'Spa', 'Restaurant'],
+ description: 'Luxurious hotel in the heart of the city with stunning views and world-class amenities.',
+ },
+ {
+ id: '2',
+ name: 'Oceanview Resort',
+ location: params.destination,
+ rating: 4.8,
+ price: 199,
+ image: 'https://images.unsplash.com/photo-1551882547-ff40c63fe5fa?w=800',
+ amenities: ['Beach Access', 'Pool', 'Spa', 'Free WiFi', 'Parking'],
+ description: 'Beachfront resort with direct access to pristine beaches and tropical paradise.',
+ },
+ {
+ id: '3',
+ name: 'City Center Inn',
+ location: params.destination,
+ rating: 4.2,
+ price: 89,
+ image: 'https://images.unsplash.com/photo-1571896349842-33c89424de2d?w=800',
+ amenities: ['Free WiFi', 'Breakfast', 'Gym'],
+ description: 'Comfortable and affordable hotel located in the bustling city center.',
+ },
+ {
+ id: '4',
+ name: 'Mountain View Lodge',
+ location: params.destination,
+ rating: 4.6,
+ price: 149,
+ image: 'https://images.unsplash.com/photo-1551882547-ff40c63fe5fa?w=800',
+ amenities: ['Mountain Views', 'Hiking Trails', 'Spa', 'Restaurant'],
+ description: 'Scenic mountain retreat with breathtaking views and outdoor activities.',
+ },
+ ];
+
+ setTimeout(() => {
+ setHotels(mockHotels);
+ track('hotel_search_results', {
+ destination: params.destination,
+ results_count: mockHotels.length,
+ });
+ }, 500);
+ };
+
+ const handleHotelSelect = (hotel: Hotel) => {
+ setSelectedHotel(hotel);
+ setShowBooking(true);
+ const nights = searchParams
+ ? Math.ceil(
+ (new Date(searchParams.checkOut).getTime() - new Date(searchParams.checkIn).getTime()) /
+ (1000 * 60 * 60 * 24)
+ )
+ : 0;
+
+ track('hotel_viewed', {
+ hotel_id: hotel.id,
+ hotel_name: hotel.name,
+ hotel_price: hotel.price,
+ hotel_rating: hotel.rating,
+ hotel_location: hotel.location,
+ hotel_amenities: hotel.amenities.join(', '),
+ destination: searchParams?.destination,
+ check_in: searchParams?.checkIn,
+ check_out: searchParams?.checkOut,
+ nights,
+ guests: searchParams?.guests,
+ estimated_total: hotel.price * nights,
+ });
+
+ track('booking_flow_started', {
+ hotel_id: hotel.id,
+ hotel_name: hotel.name,
+ step: 'hotel_selected',
+ });
+ };
+
+ const handleBookingComplete = (bookingData: any) => {
+ const nights = searchParams
+ ? Math.ceil(
+ (new Date(searchParams.checkOut).getTime() - new Date(searchParams.checkIn).getTime()) /
+ (1000 * 60 * 60 * 24)
+ )
+ : 0;
+
+ track('booking_completed', {
+ hotel_id: selectedHotel?.id,
+ hotel_name: selectedHotel?.name,
+ hotel_price: selectedHotel?.price,
+ hotel_rating: selectedHotel?.rating,
+ booking_id: bookingData.bookingId,
+ total_amount: bookingData.totalAmount,
+ subtotal: selectedHotel ? selectedHotel.price * nights : 0,
+ tax: bookingData.totalAmount * 0.1,
+ nights,
+ check_in: searchParams?.checkIn,
+ check_out: searchParams?.checkOut,
+ guests: searchParams?.guests,
+ destination: searchParams?.destination,
+ currency: 'USD',
+ booking_timestamp: new Date().toISOString(),
+ });
+
+ track('conversion', {
+ conversion_type: 'hotel_booking',
+ booking_id: bookingData.bookingId,
+ revenue: bookingData.totalAmount,
+ hotel_id: selectedHotel?.id,
+ });
+
+ alert(`Booking confirmed! Booking ID: ${bookingData.bookingId}`);
+ setShowBooking(false);
+ setSelectedHotel(null);
+ setSearchParams(null);
+ setHotels([]);
+ };
+
+ return (
+
+
+
+
+ {!showBooking ? (
+ <>
+
+ {hotels.length > 0 && (
+
+ )}
+ >
+ ) : (
+ {
+ track('booking_flow_exited', {
+ hotel_id: selectedHotel?.id,
+ step: 'booking_form',
+ });
+ setShowBooking(false);
+ setSelectedHotel(null);
+ }}
+ />
+ )}
+
+
+
+
+ );
+}
diff --git a/chatgpt-app-sample/components/AIDetection.module.css b/chatgpt-app-sample/components/AIDetection.module.css
new file mode 100644
index 00000000..266b25f1
--- /dev/null
+++ b/chatgpt-app-sample/components/AIDetection.module.css
@@ -0,0 +1,63 @@
+.section {
+ margin-bottom: 40px;
+ padding: 25px;
+ background: #f9f9f9;
+ border-radius: 8px;
+ border: 1px solid #e0e0e0;
+}
+
+.section h2 {
+ color: #667eea;
+ margin-bottom: 20px;
+ font-size: 1.5em;
+}
+
+.infoBox {
+ background: white;
+ padding: 20px;
+ border-radius: 6px;
+ margin-bottom: 15px;
+ border: 1px solid #e0e0e0;
+}
+
+.infoBox p {
+ margin-bottom: 10px;
+ padding: 8px;
+ background: #f5f5f5;
+ border-radius: 4px;
+}
+
+.infoBox strong {
+ color: #667eea;
+ display: inline-block;
+ min-width: 180px;
+}
+
+.detected {
+ color: #f56565;
+ font-weight: 600;
+}
+
+.notDetected {
+ color: #48bb78;
+ font-weight: 600;
+}
+
+.btnSecondary {
+ padding: 12px 24px;
+ border: none;
+ border-radius: 6px;
+ font-size: 14px;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all 0.3s;
+ background: #764ba2;
+ color: white;
+}
+
+.btnSecondary:hover {
+ background: #5a3a7a;
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(118, 75, 162, 0.4);
+}
+
diff --git a/chatgpt-app-sample/components/AIDetection.tsx b/chatgpt-app-sample/components/AIDetection.tsx
new file mode 100644
index 00000000..319b06a4
--- /dev/null
+++ b/chatgpt-app-sample/components/AIDetection.tsx
@@ -0,0 +1,50 @@
+'use client';
+
+import { useAIDetection } from '@/hooks/useAIDetection';
+import styles from './AIDetection.module.css';
+
+export default function AIDetection() {
+ const { detectionResults, isDetecting, refreshDetection } = useAIDetection();
+
+ if (isDetecting || !detectionResults) {
+ return (
+
+
AI Detection & Tracking
+
Detecting...
+
+ );
+ }
+
+ return (
+
+
AI Detection & Tracking
+
+
+ User Agent: {detectionResults.userAgent}
+
+
+ AI Bot Detected:{' '}
+
+ {detectionResults.isAIBot ? 'Yes' : 'No'}
+
+
+
+ AI-Assisted Browser:{' '}
+
+ {detectionResults.isAIAssisted ? 'Yes' : 'No'}
+
+
+
+ GPT App User:{' '}
+
+ {detectionResults.isGPTApp ? 'Yes' : 'No'}
+
+
+
+
+
+ );
+}
+
diff --git a/chatgpt-app-sample/components/EventTracking.module.css b/chatgpt-app-sample/components/EventTracking.module.css
new file mode 100644
index 00000000..07c5a995
--- /dev/null
+++ b/chatgpt-app-sample/components/EventTracking.module.css
@@ -0,0 +1,112 @@
+.section {
+ margin-bottom: 40px;
+ padding: 25px;
+ background: #f9f9f9;
+ border-radius: 8px;
+ border: 1px solid #e0e0e0;
+}
+
+.section h2 {
+ color: #667eea;
+ margin-bottom: 20px;
+ font-size: 1.5em;
+}
+
+.section h3 {
+ color: #764ba2;
+ margin-bottom: 15px;
+ font-size: 1.2em;
+}
+
+.buttonGroup {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 10px;
+ margin-bottom: 20px;
+}
+
+.btnSecondary {
+ padding: 12px 24px;
+ border: none;
+ border-radius: 6px;
+ font-size: 14px;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all 0.3s;
+ background: #764ba2;
+ color: white;
+}
+
+.btnSecondary:hover {
+ background: #5a3a7a;
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(118, 75, 162, 0.4);
+}
+
+.btnPrimary {
+ padding: 12px 24px;
+ border: none;
+ border-radius: 6px;
+ font-size: 14px;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all 0.3s;
+ background: #667eea;
+ color: white;
+}
+
+.btnPrimary:hover {
+ background: #5568d3;
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
+}
+
+.customEventSection {
+ margin-top: 25px;
+ padding-top: 25px;
+ border-top: 2px solid #e0e0e0;
+}
+
+.formGroup {
+ margin-bottom: 15px;
+}
+
+.formGroup label {
+ display: block;
+ margin-bottom: 5px;
+ color: #555;
+ font-weight: 500;
+}
+
+.formGroup input,
+.formGroup textarea {
+ width: 100%;
+ padding: 12px;
+ border: 2px solid #e0e0e0;
+ border-radius: 6px;
+ font-size: 14px;
+ transition: border-color 0.3s;
+}
+
+.formGroup input:focus,
+.formGroup textarea:focus {
+ outline: none;
+ border-color: #667eea;
+}
+
+.formGroup textarea {
+ resize: vertical;
+ font-family: 'Courier New', monospace;
+}
+
+@media (max-width: 768px) {
+ .buttonGroup {
+ flex-direction: column;
+ }
+
+ .btnSecondary,
+ .btnPrimary {
+ width: 100%;
+ }
+}
+
diff --git a/chatgpt-app-sample/components/EventTracking.tsx b/chatgpt-app-sample/components/EventTracking.tsx
new file mode 100644
index 00000000..699389e0
--- /dev/null
+++ b/chatgpt-app-sample/components/EventTracking.tsx
@@ -0,0 +1,125 @@
+'use client';
+
+import { useState } from 'react';
+import { useTracking } from '@/hooks/useTracking';
+import styles from './EventTracking.module.css';
+
+export default function EventTracking() {
+ const [eventName, setEventName] = useState('');
+ const [eventProperties, setEventProperties] = useState('');
+ const { track } = useTracking();
+
+ const handleTrackCustom = () => {
+ if (!eventName) {
+ alert('Please provide event name');
+ return;
+ }
+
+ try {
+ const properties = eventProperties ? JSON.parse(eventProperties) : {};
+ track(eventName, properties);
+ setEventName('');
+ setEventProperties('');
+ } catch (error: any) {
+ alert(`Invalid JSON: ${error.message}`);
+ }
+ };
+
+ return (
+
+
Event Tracking
+
+
+
+
+
+
+
+
+
+
+
Custom Event
+
+
+ setEventName(e.target.value)}
+ placeholder="e.g., custom_action"
+ />
+
+
+
+
+
+
+
+ );
+}
+
diff --git a/chatgpt-app-sample/components/HotelBooking.module.css b/chatgpt-app-sample/components/HotelBooking.module.css
new file mode 100644
index 00000000..5354c8de
--- /dev/null
+++ b/chatgpt-app-sample/components/HotelBooking.module.css
@@ -0,0 +1,172 @@
+.bookingContainer {
+ display: grid;
+ grid-template-columns: 1fr 350px;
+ gap: 2rem;
+}
+
+.bookingMain {
+ background: white;
+ border-radius: 8px;
+ padding: 2rem;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+}
+
+.hotelSummary {
+ display: flex;
+ gap: 1.5rem;
+ padding-bottom: 2rem;
+ margin-bottom: 2rem;
+ border-bottom: 1px solid #e0e0e0;
+}
+
+.summaryImage {
+ width: 200px;
+ height: 150px;
+ object-fit: cover;
+ border-radius: 8px;
+}
+
+.summaryInfo h2 {
+ color: #003580;
+ margin-bottom: 0.5rem;
+}
+
+.summaryDetails {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 0.5rem;
+ margin-top: 1rem;
+ font-size: 0.9rem;
+}
+
+.bookingForm h3 {
+ color: #003580;
+ margin-bottom: 1rem;
+ font-size: 1.25rem;
+}
+
+.formGrid {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 1rem;
+ margin-bottom: 2rem;
+}
+
+.formGroup {
+ display: flex;
+ flex-direction: column;
+}
+
+.formGroup label {
+ font-size: 0.875rem;
+ color: #333;
+ margin-bottom: 0.5rem;
+ font-weight: 500;
+}
+
+.formGroup input {
+ padding: 0.75rem;
+ border: 1px solid #ddd;
+ border-radius: 4px;
+ font-size: 1rem;
+}
+
+.formGroup input:focus {
+ outline: none;
+ border-color: #003580;
+}
+
+.paymentOptions {
+ display: flex;
+ gap: 2rem;
+ margin-bottom: 2rem;
+}
+
+.paymentOptions label {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ cursor: pointer;
+}
+
+.formActions {
+ display: flex;
+ gap: 1rem;
+ justify-content: flex-end;
+}
+
+.cancelButton {
+ background: #f0f0f0;
+ color: #333;
+ border: none;
+ padding: 0.75rem 2rem;
+ border-radius: 4px;
+ font-size: 1rem;
+ font-weight: 600;
+ cursor: pointer;
+}
+
+.cancelButton:hover {
+ background: #e0e0e0;
+}
+
+.submitButton {
+ background: #003580;
+ color: white;
+ border: none;
+ padding: 0.75rem 2rem;
+ border-radius: 4px;
+ font-size: 1rem;
+ font-weight: 600;
+ cursor: pointer;
+}
+
+.submitButton:hover {
+ background: #004494;
+}
+
+.bookingSidebar {
+ background: white;
+ border-radius: 8px;
+ padding: 2rem;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+ height: fit-content;
+ position: sticky;
+ top: 2rem;
+}
+
+.priceSummary h3 {
+ color: #003580;
+ margin-bottom: 1.5rem;
+ font-size: 1.25rem;
+}
+
+.priceRow {
+ display: flex;
+ justify-content: space-between;
+ padding: 0.75rem 0;
+ border-bottom: 1px solid #e0e0e0;
+ color: #666;
+}
+
+.priceTotal {
+ display: flex;
+ justify-content: space-between;
+ padding: 1rem 0;
+ margin-top: 1rem;
+ border-top: 2px solid #003580;
+ font-size: 1.25rem;
+ font-weight: 600;
+ color: #003580;
+}
+
+@media (max-width: 1024px) {
+ .bookingContainer {
+ grid-template-columns: 1fr;
+ }
+
+ .bookingSidebar {
+ position: static;
+ }
+}
+
diff --git a/chatgpt-app-sample/components/HotelBooking.tsx b/chatgpt-app-sample/components/HotelBooking.tsx
new file mode 100644
index 00000000..70e0d0cc
--- /dev/null
+++ b/chatgpt-app-sample/components/HotelBooking.tsx
@@ -0,0 +1,246 @@
+'use client';
+
+import { useState, useEffect } from 'react';
+import { Hotel } from '@/app/page';
+import { useTracking } from '@/hooks/useTracking';
+import styles from './HotelBooking.module.css';
+
+interface HotelBookingProps {
+ hotel: Hotel;
+ searchParams: { destination: string; checkIn: string; checkOut: string; guests: number };
+ onComplete: (bookingData: { bookingId: string; totalAmount: number }) => void;
+ onCancel: () => void;
+}
+
+export default function HotelBooking({ hotel, searchParams, onComplete, onCancel }: HotelBookingProps) {
+ const [guestInfo, setGuestInfo] = useState({
+ firstName: '',
+ lastName: '',
+ email: '',
+ phone: '',
+ });
+ const [paymentMethod, setPaymentMethod] = useState('credit_card');
+ const { track } = useTracking();
+
+ const nights = Math.ceil(
+ (new Date(searchParams.checkOut).getTime() - new Date(searchParams.checkIn).getTime()) /
+ (1000 * 60 * 60 * 24)
+ );
+
+ const subtotal = hotel.price * nights;
+ const tax = subtotal * 0.1;
+ const total = subtotal + tax;
+
+ useEffect(() => {
+ track('booking_page_viewed', {
+ hotel_id: hotel.id,
+ hotel_name: hotel.name,
+ hotel_price: hotel.price,
+ check_in: searchParams.checkIn,
+ check_out: searchParams.checkOut,
+ guests: searchParams.guests,
+ nights,
+ total_amount: total,
+ });
+ }, [hotel.id, hotel.name, hotel.price, searchParams.checkIn, searchParams.checkOut, searchParams.guests, nights, total, track]);
+
+ const handleFieldChange = (field: string, value: string) => {
+ track('booking_form_field_changed', {
+ field_name: field,
+ has_value: !!value,
+ hotel_id: hotel.id,
+ });
+ };
+
+ const handleSubmit = (e: React.FormEvent) => {
+ e.preventDefault();
+ if (!guestInfo.firstName || !guestInfo.lastName || !guestInfo.email || !guestInfo.phone) {
+ alert('Please fill in all guest information');
+ return;
+ }
+
+ track('booking_started', {
+ hotel_id: hotel.id,
+ hotel_name: hotel.name,
+ hotel_price: hotel.price,
+ total_amount: total,
+ subtotal,
+ tax,
+ nights,
+ guests: searchParams.guests,
+ check_in: searchParams.checkIn,
+ check_out: searchParams.checkOut,
+ payment_method: paymentMethod,
+ has_email: !!guestInfo.email,
+ has_phone: !!guestInfo.phone,
+ });
+
+ const bookingId = `BK${Date.now()}`;
+ onComplete({ bookingId, totalAmount: total });
+ };
+
+ const handleCancel = () => {
+ track('booking_cancelled', {
+ hotel_id: hotel.id,
+ hotel_name: hotel.name,
+ total_amount: total,
+ form_progress: {
+ has_first_name: !!guestInfo.firstName,
+ has_last_name: !!guestInfo.lastName,
+ has_email: !!guestInfo.email,
+ has_phone: !!guestInfo.phone,
+ },
+ });
+ onCancel();
+ };
+
+ return (
+
+
+
+

+
+
{hotel.name}
+
{hotel.location}
+
+
+ Check-in: {new Date(searchParams.checkIn).toLocaleDateString()}
+
+
+ Check-out: {new Date(searchParams.checkOut).toLocaleDateString()}
+
+
+ Guests: {searchParams.guests}
+
+
+ Nights: {nights}
+
+
+
+
+
+
+
+
+
+
+
Price Summary
+
+ ${hotel.price} × {nights} nights
+ ${subtotal.toFixed(2)}
+
+
+ Taxes & Fees
+ ${tax.toFixed(2)}
+
+
+ Total
+ ${total.toFixed(2)}
+
+
+
+
+ );
+}
+
diff --git a/chatgpt-app-sample/components/HotelResults.module.css b/chatgpt-app-sample/components/HotelResults.module.css
new file mode 100644
index 00000000..7e9d9d50
--- /dev/null
+++ b/chatgpt-app-sample/components/HotelResults.module.css
@@ -0,0 +1,175 @@
+.resultsContainer {
+ background: white;
+ border-radius: 8px;
+ padding: 2rem;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+}
+
+.resultsHeader {
+ margin-bottom: 2rem;
+ padding-bottom: 1rem;
+ border-bottom: 1px solid #e0e0e0;
+}
+
+.resultsHeader h2 {
+ font-size: 1.5rem;
+ color: #003580;
+ margin-bottom: 0.5rem;
+}
+
+.dates {
+ color: #666;
+ font-size: 0.9rem;
+}
+
+.hotelsList {
+ display: flex;
+ flex-direction: column;
+ gap: 1.5rem;
+}
+
+.hotelCard {
+ display: grid;
+ grid-template-columns: 300px 1fr 200px;
+ gap: 1.5rem;
+ padding: 1.5rem;
+ border: 1px solid #e0e0e0;
+ border-radius: 8px;
+ cursor: pointer;
+ transition: all 0.2s;
+}
+
+.hotelCard:hover {
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+ border-color: #003580;
+}
+
+.hotelImage {
+ position: relative;
+ border-radius: 8px;
+ overflow: hidden;
+ height: 200px;
+}
+
+.hotelImage img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+}
+
+.ratingBadge {
+ position: absolute;
+ top: 10px;
+ right: 10px;
+ background: #003580;
+ color: white;
+ padding: 0.5rem;
+ border-radius: 4px;
+ font-weight: 600;
+}
+
+.ratingValue {
+ font-size: 1rem;
+}
+
+.hotelInfo {
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+}
+
+.hotelName {
+ font-size: 1.25rem;
+ color: #003580;
+ margin: 0;
+ font-weight: 600;
+}
+
+.hotelLocation {
+ color: #666;
+ font-size: 0.9rem;
+}
+
+.hotelDescription {
+ color: #333;
+ font-size: 0.9rem;
+ line-height: 1.5;
+ margin: 0.5rem 0;
+}
+
+.amenities {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.5rem;
+ margin-top: auto;
+}
+
+.amenity {
+ background: #f0f0f0;
+ padding: 0.25rem 0.75rem;
+ border-radius: 4px;
+ font-size: 0.85rem;
+ color: #333;
+}
+
+.hotelPrice {
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ align-items: flex-end;
+}
+
+.priceContainer {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-end;
+ gap: 0.25rem;
+}
+
+.priceLabel {
+ font-size: 0.85rem;
+ color: #666;
+}
+
+.price {
+ font-size: 1.5rem;
+ font-weight: 600;
+ color: #003580;
+}
+
+.totalPrice {
+ font-size: 0.9rem;
+ color: #666;
+}
+
+.selectButton {
+ background: #003580;
+ color: white;
+ border: none;
+ padding: 0.75rem 1.5rem;
+ border-radius: 4px;
+ font-size: 1rem;
+ font-weight: 600;
+ cursor: pointer;
+ transition: background 0.2s;
+ width: 100%;
+}
+
+.selectButton:hover {
+ background: #004494;
+}
+
+@media (max-width: 1024px) {
+ .hotelCard {
+ grid-template-columns: 1fr;
+ }
+
+ .hotelImage {
+ height: 250px;
+ }
+
+ .hotelPrice {
+ align-items: stretch;
+ }
+}
+
diff --git a/chatgpt-app-sample/components/HotelResults.tsx b/chatgpt-app-sample/components/HotelResults.tsx
new file mode 100644
index 00000000..11ef82a3
--- /dev/null
+++ b/chatgpt-app-sample/components/HotelResults.tsx
@@ -0,0 +1,107 @@
+'use client';
+
+import { useEffect } from 'react';
+import { Hotel } from '@/app/page';
+import { useTracking } from '@/hooks/useTracking';
+import styles from './HotelResults.module.css';
+
+interface HotelResultsProps {
+ hotels: Hotel[];
+ searchParams: { destination: string; checkIn: string; checkOut: string; guests: number };
+ onHotelSelect: (hotel: Hotel) => void;
+}
+
+export default function HotelResults({ hotels, searchParams, onHotelSelect }: HotelResultsProps) {
+ const { track } = useTracking();
+ const nights = Math.ceil(
+ (new Date(searchParams.checkOut).getTime() - new Date(searchParams.checkIn).getTime()) /
+ (1000 * 60 * 60 * 24)
+ );
+
+ useEffect(() => {
+ if (hotels.length > 0) {
+ track('hotel_results_viewed', {
+ destination: searchParams.destination,
+ results_count: hotels.length,
+ check_in: searchParams.checkIn,
+ check_out: searchParams.checkOut,
+ nights,
+ guests: searchParams.guests,
+ });
+
+ hotels.forEach((hotel, index) => {
+ track('hotel_impression', {
+ hotel_id: hotel.id,
+ hotel_name: hotel.name,
+ hotel_price: hotel.price,
+ hotel_rating: hotel.rating,
+ position: index + 1,
+ destination: searchParams.destination,
+ });
+ });
+ }
+ }, [hotels, searchParams, nights, track]);
+
+ return (
+
+
+
+ {hotels.length} properties found in {searchParams.destination}
+
+
+ {new Date(searchParams.checkIn).toLocaleDateString()} -{' '}
+ {new Date(searchParams.checkOut).toLocaleDateString()} • {nights} nights • {searchParams.guests} guest
+ {searchParams.guests > 1 ? 's' : ''}
+
+
+
+
+ {hotels.map((hotel, index) => (
+
{
+ track('hotel_card_clicked', {
+ hotel_id: hotel.id,
+ hotel_name: hotel.name,
+ hotel_price: hotel.price,
+ hotel_rating: hotel.rating,
+ position: index + 1,
+ destination: searchParams.destination,
+ });
+ onHotelSelect(hotel);
+ }}
+ >
+
+

+
+ {hotel.rating}
+
+
+
+
{hotel.name}
+
{hotel.location}
+
{hotel.description}
+
+ {hotel.amenities.map((amenity, index) => (
+
+ {amenity}
+
+ ))}
+
+
+
+
+ Price per night
+ ${hotel.price}
+ ${hotel.price * nights} total
+
+
+
+
+ ))}
+
+
+ );
+}
+
diff --git a/chatgpt-app-sample/components/HotelSearch.module.css b/chatgpt-app-sample/components/HotelSearch.module.css
new file mode 100644
index 00000000..f8e2255e
--- /dev/null
+++ b/chatgpt-app-sample/components/HotelSearch.module.css
@@ -0,0 +1,78 @@
+.searchContainer {
+ background: white;
+ border-radius: 8px;
+ padding: 2rem;
+ margin-bottom: 2rem;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+}
+
+.title {
+ font-size: 1.5rem;
+ color: #003580;
+ margin-bottom: 1.5rem;
+ font-weight: 600;
+}
+
+.searchForm {
+ width: 100%;
+}
+
+.formRow {
+ display: grid;
+ grid-template-columns: 2fr 1fr 1fr 1fr auto;
+ gap: 1rem;
+ align-items: end;
+}
+
+.formGroup {
+ display: flex;
+ flex-direction: column;
+}
+
+.formGroup label {
+ font-size: 0.875rem;
+ color: #333;
+ margin-bottom: 0.5rem;
+ font-weight: 500;
+}
+
+.formGroup input {
+ padding: 0.75rem;
+ border: 1px solid #ddd;
+ border-radius: 4px;
+ font-size: 1rem;
+ transition: border-color 0.2s;
+}
+
+.formGroup input:focus {
+ outline: none;
+ border-color: #003580;
+}
+
+.searchButton {
+ background: #003580;
+ color: white;
+ border: none;
+ padding: 0.75rem 2rem;
+ border-radius: 4px;
+ font-size: 1rem;
+ font-weight: 600;
+ cursor: pointer;
+ transition: background 0.2s;
+ white-space: nowrap;
+}
+
+.searchButton:hover {
+ background: #004494;
+}
+
+@media (max-width: 1024px) {
+ .formRow {
+ grid-template-columns: 1fr;
+ }
+
+ .searchButton {
+ width: 100%;
+ }
+}
+
diff --git a/chatgpt-app-sample/components/HotelSearch.tsx b/chatgpt-app-sample/components/HotelSearch.tsx
new file mode 100644
index 00000000..a62ebf44
--- /dev/null
+++ b/chatgpt-app-sample/components/HotelSearch.tsx
@@ -0,0 +1,116 @@
+'use client';
+
+import { useState, useEffect } from 'react';
+import { useTracking } from '@/hooks/useTracking';
+import styles from './HotelSearch.module.css';
+
+interface HotelSearchProps {
+ onSearch: (params: { destination: string; checkIn: string; checkOut: string; guests: number }) => void;
+}
+
+export default function HotelSearch({ onSearch }: HotelSearchProps) {
+ const [destination, setDestination] = useState('');
+ const [checkIn, setCheckIn] = useState('');
+ const [checkOut, setCheckOut] = useState('');
+ const [guests, setGuests] = useState(2);
+ const { track } = useTracking();
+
+ useEffect(() => {
+ track('search_form_viewed', {
+ page: 'home',
+ component: 'hotel_search',
+ });
+ }, [track]);
+
+ const today = new Date().toISOString().split('T')[0];
+ const tomorrow = new Date(Date.now() + 86400000).toISOString().split('T')[0];
+
+ const handleSubmit = (e: React.FormEvent) => {
+ e.preventDefault();
+ if (!destination || !checkIn || !checkOut) {
+ track('search_form_error', {
+ error_type: 'missing_fields',
+ has_destination: !!destination,
+ has_check_in: !!checkIn,
+ has_check_out: !!checkOut,
+ });
+ alert('Please fill in all fields');
+ return;
+ }
+
+ track('search_form_submitted', {
+ destination,
+ check_in: checkIn,
+ check_out: checkOut,
+ guests,
+ nights: Math.ceil(
+ (new Date(checkOut).getTime() - new Date(checkIn).getTime()) / (1000 * 60 * 60 * 24)
+ ),
+ });
+
+ onSearch({ destination, checkIn, checkOut, guests });
+ };
+
+ return (
+
+
Find your perfect stay
+
+
+ );
+}
+
diff --git a/chatgpt-app-sample/components/SessionManagement.module.css b/chatgpt-app-sample/components/SessionManagement.module.css
new file mode 100644
index 00000000..227dea38
--- /dev/null
+++ b/chatgpt-app-sample/components/SessionManagement.module.css
@@ -0,0 +1,67 @@
+.section {
+ margin-bottom: 40px;
+ padding: 25px;
+ background: #f9f9f9;
+ border-radius: 8px;
+ border: 1px solid #e0e0e0;
+}
+
+.section h2 {
+ color: #667eea;
+ margin-bottom: 20px;
+ font-size: 1.5em;
+}
+
+.buttonGroup {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 10px;
+}
+
+.btnWarning {
+ padding: 12px 24px;
+ border: none;
+ border-radius: 6px;
+ font-size: 14px;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all 0.3s;
+ background: #f56565;
+ color: white;
+}
+
+.btnWarning:hover {
+ background: #e53e3e;
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(245, 101, 101, 0.4);
+}
+
+.btnSecondary {
+ padding: 12px 24px;
+ border: none;
+ border-radius: 6px;
+ font-size: 14px;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all 0.3s;
+ background: #764ba2;
+ color: white;
+}
+
+.btnSecondary:hover {
+ background: #5a3a7a;
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(118, 75, 162, 0.4);
+}
+
+@media (max-width: 768px) {
+ .buttonGroup {
+ flex-direction: column;
+ }
+
+ .btnWarning,
+ .btnSecondary {
+ width: 100%;
+ }
+}
+
diff --git a/chatgpt-app-sample/components/SessionManagement.tsx b/chatgpt-app-sample/components/SessionManagement.tsx
new file mode 100644
index 00000000..04429905
--- /dev/null
+++ b/chatgpt-app-sample/components/SessionManagement.tsx
@@ -0,0 +1,32 @@
+'use client';
+
+import { useState } from 'react';
+import { useTracking } from '@/hooks/useTracking';
+import styles from './SessionManagement.module.css';
+
+export default function SessionManagement() {
+ const { destroy, updateId } = useTracking();
+ const [newUserId, setNewUserId] = useState('');
+
+ const handleUpdateUserId = () => {
+ const userId = prompt('Enter new User ID:');
+ if (userId) {
+ updateId(userId);
+ }
+ };
+
+ return (
+
+
Session Management
+
+
+
+
+
+ );
+}
+
diff --git a/chatgpt-app-sample/components/TrackingLogs.module.css b/chatgpt-app-sample/components/TrackingLogs.module.css
new file mode 100644
index 00000000..e23521fc
--- /dev/null
+++ b/chatgpt-app-sample/components/TrackingLogs.module.css
@@ -0,0 +1,74 @@
+.section {
+ margin-bottom: 40px;
+ padding: 25px;
+ background: #f9f9f9;
+ border-radius: 8px;
+ border: 1px solid #e0e0e0;
+}
+
+.section h2 {
+ color: #667eea;
+ margin-bottom: 20px;
+ font-size: 1.5em;
+}
+
+.logsContainer {
+ background: #1e1e1e;
+ color: #d4d4d4;
+ padding: 20px;
+ border-radius: 6px;
+ max-height: 400px;
+ overflow-y: auto;
+ font-family: 'Courier New', monospace;
+ font-size: 12px;
+ margin-bottom: 15px;
+}
+
+.emptyLogs {
+ color: #888;
+ text-align: center;
+ padding: 20px;
+}
+
+.logEntry {
+ margin-bottom: 10px;
+ padding: 8px;
+ border-left: 3px solid #667eea;
+ padding-left: 15px;
+}
+
+.logEntry.success {
+ border-left-color: #48bb78;
+}
+
+.logEntry.error {
+ border-left-color: #f56565;
+}
+
+.logEntry.info {
+ border-left-color: #4299e1;
+}
+
+.logTimestamp {
+ color: #888;
+ font-size: 11px;
+}
+
+.btnSecondary {
+ padding: 12px 24px;
+ border: none;
+ border-radius: 6px;
+ font-size: 14px;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all 0.3s;
+ background: #764ba2;
+ color: white;
+}
+
+.btnSecondary:hover {
+ background: #5a3a7a;
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(118, 75, 162, 0.4);
+}
+
diff --git a/chatgpt-app-sample/components/TrackingLogs.tsx b/chatgpt-app-sample/components/TrackingLogs.tsx
new file mode 100644
index 00000000..b78ca2ef
--- /dev/null
+++ b/chatgpt-app-sample/components/TrackingLogs.tsx
@@ -0,0 +1,32 @@
+'use client';
+
+import { LogEntry } from '@/hooks/useTracking';
+import styles from './TrackingLogs.module.css';
+
+interface TrackingLogsProps {
+ logs: LogEntry[];
+ onClear: () => void;
+}
+
+export default function TrackingLogs({ logs, onClear }: TrackingLogsProps) {
+ return (
+
+
Tracking Logs
+
+ {logs.length === 0 ? (
+
No logs yet. Start tracking events to see logs here.
+ ) : (
+ logs.slice(-50).map((log, index) => (
+
+ [{log.timestamp}] {log.message}
+
+ ))
+ )}
+
+
+
+ );
+}
+
diff --git a/chatgpt-app-sample/components/UserIdentification.module.css b/chatgpt-app-sample/components/UserIdentification.module.css
new file mode 100644
index 00000000..501dd8dd
--- /dev/null
+++ b/chatgpt-app-sample/components/UserIdentification.module.css
@@ -0,0 +1,57 @@
+.section {
+ margin-bottom: 40px;
+ padding: 25px;
+ background: #f9f9f9;
+ border-radius: 8px;
+ border: 1px solid #e0e0e0;
+}
+
+.section h2 {
+ color: #667eea;
+ margin-bottom: 20px;
+ font-size: 1.5em;
+}
+
+.formGroup {
+ margin-bottom: 15px;
+}
+
+.formGroup label {
+ display: block;
+ margin-bottom: 5px;
+ color: #555;
+ font-weight: 500;
+}
+
+.formGroup input {
+ width: 100%;
+ padding: 12px;
+ border: 2px solid #e0e0e0;
+ border-radius: 6px;
+ font-size: 14px;
+ transition: border-color 0.3s;
+}
+
+.formGroup input:focus {
+ outline: none;
+ border-color: #667eea;
+}
+
+.btnPrimary {
+ padding: 12px 24px;
+ border: none;
+ border-radius: 6px;
+ font-size: 14px;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all 0.3s;
+ background: #667eea;
+ color: white;
+}
+
+.btnPrimary:hover {
+ background: #5568d3;
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
+}
+
diff --git a/chatgpt-app-sample/components/UserIdentification.tsx b/chatgpt-app-sample/components/UserIdentification.tsx
new file mode 100644
index 00000000..0ed5704b
--- /dev/null
+++ b/chatgpt-app-sample/components/UserIdentification.tsx
@@ -0,0 +1,72 @@
+'use client';
+
+import { useState } from 'react';
+import { useTracking } from '@/hooks/useTracking';
+import styles from './UserIdentification.module.css';
+
+export default function UserIdentification() {
+ const [userId, setUserId] = useState('');
+ const [userName, setUserName] = useState('');
+ const [userEmail, setUserEmail] = useState('');
+ const [userMobile, setUserMobile] = useState('');
+ const { identify } = useTracking();
+
+ const handleIdentify = () => {
+ identify({
+ uid: userId || undefined,
+ u_fn: userName || undefined,
+ u_em: userEmail || undefined,
+ u_mb: userMobile || undefined,
+ });
+ };
+
+ return (
+
+ );
+}
+
diff --git a/chatgpt-app-sample/components/UserProfile.module.css b/chatgpt-app-sample/components/UserProfile.module.css
new file mode 100644
index 00000000..acf5e1ac
--- /dev/null
+++ b/chatgpt-app-sample/components/UserProfile.module.css
@@ -0,0 +1,57 @@
+.profileContainer {
+ background: white;
+ border-radius: 8px;
+ padding: 1.5rem;
+ margin-bottom: 1.5rem;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+}
+
+.title {
+ font-size: 1.1rem;
+ color: #003580;
+ margin-bottom: 1rem;
+ font-weight: 600;
+}
+
+.formGroup {
+ margin-bottom: 1rem;
+}
+
+.formGroup label {
+ display: block;
+ font-size: 0.875rem;
+ color: #333;
+ margin-bottom: 0.5rem;
+ font-weight: 500;
+}
+
+.formGroup input {
+ width: 100%;
+ padding: 0.5rem;
+ border: 1px solid #ddd;
+ border-radius: 4px;
+ font-size: 0.9rem;
+}
+
+.formGroup input:focus {
+ outline: none;
+ border-color: #003580;
+}
+
+.identifyButton {
+ width: 100%;
+ background: #003580;
+ color: white;
+ border: none;
+ padding: 0.75rem;
+ border-radius: 4px;
+ font-size: 0.9rem;
+ font-weight: 600;
+ cursor: pointer;
+ transition: background 0.2s;
+}
+
+.identifyButton:hover {
+ background: #004494;
+}
+
diff --git a/chatgpt-app-sample/components/UserProfile.tsx b/chatgpt-app-sample/components/UserProfile.tsx
new file mode 100644
index 00000000..d6cbc696
--- /dev/null
+++ b/chatgpt-app-sample/components/UserProfile.tsx
@@ -0,0 +1,76 @@
+'use client';
+
+import { useState } from 'react';
+import { useTracking } from '@/hooks/useTracking';
+import styles from './UserProfile.module.css';
+
+export default function UserProfile() {
+ const [userId, setUserId] = useState('');
+ const [userName, setUserName] = useState('');
+ const [userEmail, setUserEmail] = useState('');
+ const [userMobile, setUserMobile] = useState('');
+ const { identify } = useTracking();
+
+ const handleIdentify = () => {
+ if (!userId && !userEmail) {
+ alert('Please provide User ID or Email');
+ return;
+ }
+ identify({
+ uid: userId || undefined,
+ u_fn: userName || undefined,
+ u_em: userEmail || undefined,
+ u_mb: userMobile || undefined,
+ });
+ };
+
+ return (
+
+ );
+}
+
diff --git a/chatgpt-app-sample/hooks/useAIDetection.ts b/chatgpt-app-sample/hooks/useAIDetection.ts
new file mode 100644
index 00000000..f2bcb0ea
--- /dev/null
+++ b/chatgpt-app-sample/hooks/useAIDetection.ts
@@ -0,0 +1,63 @@
+import { useEffect, useState } from 'react';
+import { aiDetection, DetectionResults } from '@/lib/ai-detection';
+import { addUserAttribute, trackEvent } from '@/lib/moengage';
+
+export const useAIDetection = () => {
+ const [detectionResults, setDetectionResults] = useState(null);
+ const [isDetecting, setIsDetecting] = useState(true);
+
+ useEffect(() => {
+ const results = aiDetection.performFullDetection();
+ setDetectionResults(results);
+ setIsDetecting(false);
+
+ trackDetectionResults(results);
+ }, []);
+
+ const refreshDetection = () => {
+ setIsDetecting(true);
+ const results = aiDetection.performFullDetection();
+ setDetectionResults(results);
+ setIsDetecting(false);
+ trackDetectionResults(results);
+ };
+
+ const trackDetectionResults = (results: DetectionResults) => {
+ const attributes = {
+ ai_bot_detected: results.isAIBot,
+ ai_assisted_browser: results.isAIAssisted,
+ gpt_app_user: results.isGPTApp,
+ user_agent: results.userAgent,
+ detection_timestamp: new Date().toISOString(),
+ };
+
+ addUserAttribute(attributes);
+
+ if (results.isAIAssisted) {
+ addUserAttribute({ ai_assisted: true });
+ }
+
+ if (results.isGPTApp) {
+ addUserAttribute({ gpt_app_user: true });
+ trackEvent('gpt_app_session_start', {
+ app_url: typeof window !== 'undefined' ? window.location.href : '',
+ timestamp: new Date().toISOString(),
+ });
+ }
+
+ trackEvent('ai_detection_performed', {
+ is_ai_bot: results.isAIBot,
+ is_ai_assisted: results.isAIAssisted,
+ is_gpt_app: results.isGPTApp,
+ detection_details: JSON.stringify(results.detectionDetails),
+ });
+ };
+
+ return {
+ detectionResults,
+ isDetecting,
+ refreshDetection,
+ shouldBlockTracking: aiDetection.shouldBlockTracking(),
+ };
+};
+
diff --git a/chatgpt-app-sample/hooks/useMoEngage.ts b/chatgpt-app-sample/hooks/useMoEngage.ts
new file mode 100644
index 00000000..8969a0fa
--- /dev/null
+++ b/chatgpt-app-sample/hooks/useMoEngage.ts
@@ -0,0 +1,29 @@
+import { useEffect, useState } from 'react';
+import { initializeMoEngage, isMoEngageReady, MoEngageConfig } from '@/lib/moengage';
+
+export const useMoEngage = (config: MoEngageConfig | null) => {
+ const [isReady, setIsReady] = useState(false);
+
+ useEffect(() => {
+ if (!config || typeof window === 'undefined') return;
+
+ if (isMoEngageReady()) {
+ setIsReady(true);
+ return;
+ }
+
+ initializeMoEngage(config);
+
+ const checkReady = setInterval(() => {
+ if (isMoEngageReady()) {
+ setIsReady(true);
+ clearInterval(checkReady);
+ }
+ }, 100);
+
+ return () => clearInterval(checkReady);
+ }, [config]);
+
+ return { isReady };
+};
+
diff --git a/chatgpt-app-sample/hooks/useTracking.ts b/chatgpt-app-sample/hooks/useTracking.ts
new file mode 100644
index 00000000..1c153531
--- /dev/null
+++ b/chatgpt-app-sample/hooks/useTracking.ts
@@ -0,0 +1,113 @@
+import { useCallback } from 'react';
+import { trackEvent, identifyUser, destroySession, updateUserId } from '@/lib/moengage';
+import { aiDetection } from '@/lib/ai-detection';
+
+export interface LogEntry {
+ timestamp: string;
+ message: string;
+ type: 'success' | 'error' | 'info';
+}
+
+export const useTracking = (onLog?: (log: LogEntry) => void) => {
+ const log = useCallback(
+ (message: string, type: LogEntry['type'] = 'info') => {
+ const logEntry: LogEntry = {
+ timestamp: new Date().toLocaleTimeString(),
+ message,
+ type,
+ };
+ onLog?.(logEntry);
+ },
+ [onLog]
+ );
+
+ const track = useCallback(
+ (eventName: string, eventProperties: Record = {}) => {
+ if (aiDetection.shouldBlockTracking()) {
+ log(`Event blocked (AI Bot detected): ${eventName}`, 'info');
+ return;
+ }
+
+ const detectionResults = aiDetection.getDetectionResults();
+ const enhancedProperties = {
+ ...eventProperties,
+ ai_platform: detectionResults.isGPTApp ? 'chatgpt' : 'web',
+ is_ai_assisted: detectionResults.isAIAssisted,
+ is_gpt_app: detectionResults.isGPTApp,
+ timestamp: new Date().toISOString(),
+ };
+
+ trackEvent(eventName, enhancedProperties);
+ log(`Event tracked: ${eventName}`, 'success');
+ },
+ [log]
+ );
+
+ const identify = useCallback(
+ (userData: { uid?: string; u_fn?: string; u_em?: string; u_mb?: string; [key: string]: any }) => {
+ if (!userData.uid && !userData.u_em) {
+ log('Please provide User ID or Email', 'error');
+ return;
+ }
+
+ try {
+ identifyUser(userData);
+
+ const detectionResults = aiDetection.getDetectionResults();
+ if (detectionResults.isAIAssisted) {
+ identifyUser({ ...userData, ai_assisted: true });
+ }
+ if (detectionResults.isGPTApp) {
+ identifyUser({ ...userData, gpt_app_user: true });
+ }
+
+ log(`User identified: ${userData.uid || userData.u_em}`, 'success');
+ track('user_identified', {
+ has_name: !!userData.u_fn,
+ has_email: !!userData.u_em,
+ has_mobile: !!userData.u_mb,
+ });
+ } catch (error: any) {
+ log(`Error identifying user: ${error.message}`, 'error');
+ }
+ },
+ [log, track]
+ );
+
+ const destroy = useCallback(() => {
+ try {
+ destroySession();
+ log('Session destroyed', 'success');
+ track('session_destroyed', {
+ timestamp: new Date().toISOString(),
+ });
+ } catch (error: any) {
+ log(`Error destroying session: ${error.message}`, 'error');
+ }
+ }, [log, track]);
+
+ const updateId = useCallback(
+ (newUserId: string) => {
+ try {
+ updateUserId(newUserId);
+ log(`User ID updated to: ${newUserId}`, 'success');
+ track('user_id_updated', {
+ new_user_id: newUserId,
+ timestamp: new Date().toISOString(),
+ });
+ } catch (error: any) {
+ log(`Error updating user ID: ${error.message}`, 'error');
+ }
+ },
+ [log, track]
+ );
+
+ return {
+ track,
+ identify,
+ destroy,
+ updateId,
+ log,
+ };
+};
+
diff --git a/chatgpt-app-sample/lib/ai-detection.ts b/chatgpt-app-sample/lib/ai-detection.ts
new file mode 100644
index 00000000..ced9e003
--- /dev/null
+++ b/chatgpt-app-sample/lib/ai-detection.ts
@@ -0,0 +1,159 @@
+export interface DetectionResults {
+ isAIBot: boolean;
+ isAIAssisted: boolean;
+ isGPTApp: boolean;
+ userAgent: string;
+ detectionDetails: {
+ botDetection?: {
+ detected: boolean;
+ matchedBots: string[];
+ };
+ aiAssistedDetection?: {
+ detected: boolean;
+ matchedBrowsers: string[];
+ hasAIMarkers: boolean;
+ };
+ gptAppDetection?: {
+ detected: boolean;
+ inIframe: boolean;
+ parentUrl: string | null;
+ };
+ };
+}
+
+export class AIDetection {
+ private knownAIBots = [
+ 'GPTBot',
+ 'ChatGPT-User',
+ 'CCBot',
+ 'anthropic-ai',
+ 'ClaudeBot',
+ 'PerplexityBot',
+ 'YouBot',
+ 'Google-Extended',
+ 'Bingbot',
+ 'Googlebot',
+ 'facebookexternalhit',
+ 'Twitterbot',
+ 'LinkedInBot',
+ 'Slackbot',
+ 'Discordbot',
+ 'Applebot-Extended',
+ ];
+
+ private aiAssistedBrowsers = ['Arc', 'Arc Browser', 'Opera GX', 'Brave', 'Vivaldi'];
+
+ private aiAssistedMarkers = ['arc', 'ai-assistant', 'ai-powered', 'copilot', 'assistant'];
+
+ private detectionResults: DetectionResults = {
+ isAIBot: false,
+ isAIAssisted: false,
+ isGPTApp: false,
+ userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : '',
+ detectionDetails: {},
+ };
+
+ detectAIBot(): boolean {
+ if (typeof navigator === 'undefined') return false;
+
+ const userAgent = navigator.userAgent;
+ const isBot = this.knownAIBots.some(
+ (bot) => userAgent.includes(bot) || userAgent.toLowerCase().includes(bot.toLowerCase())
+ );
+
+ this.detectionResults.isAIBot = isBot;
+ this.detectionResults.detectionDetails.botDetection = {
+ detected: isBot,
+ matchedBots: this.knownAIBots.filter(
+ (bot) => userAgent.includes(bot) || userAgent.toLowerCase().includes(bot.toLowerCase())
+ ),
+ };
+
+ return isBot;
+ }
+
+ detectAIAssistedBrowser(): boolean {
+ if (typeof navigator === 'undefined') return false;
+
+ const userAgent = navigator.userAgent;
+ const isAIAssisted =
+ this.aiAssistedBrowsers.some(
+ (browser) => userAgent.includes(browser) || userAgent.toLowerCase().includes(browser.toLowerCase())
+ ) ||
+ this.aiAssistedMarkers.some((marker) => userAgent.toLowerCase().includes(marker.toLowerCase()));
+
+ const hasAIMarkers = this.checkAIMarkers();
+
+ this.detectionResults.isAIAssisted = isAIAssisted || hasAIMarkers;
+ this.detectionResults.detectionDetails.aiAssistedDetection = {
+ detected: isAIAssisted || hasAIMarkers,
+ matchedBrowsers: this.aiAssistedBrowsers.filter(
+ (browser) => userAgent.includes(browser) || userAgent.toLowerCase().includes(browser.toLowerCase())
+ ),
+ hasAIMarkers: hasAIMarkers,
+ };
+
+ return isAIAssisted || hasAIMarkers;
+ }
+
+ private checkAIMarkers(): boolean {
+ if (typeof window === 'undefined') return false;
+
+ const windowObj = window as any;
+ const navigatorObj = navigator as any;
+
+ const markers = [
+ windowObj.arc !== undefined,
+ windowObj.copilot !== undefined,
+ navigatorObj.aiAssistant !== undefined,
+ windowObj.__ai_assistant__ !== undefined,
+ navigatorObj.userAgentData &&
+ navigatorObj.userAgentData.brands &&
+ navigatorObj.userAgentData.brands.some(
+ (brand: any) => brand.brand && brand.brand.toLowerCase().includes('ai')
+ ),
+ ];
+
+ return markers.some((marker) => marker === true);
+ }
+
+ detectGPTApp(): boolean {
+ if (typeof window === 'undefined') return false;
+
+ const isGPTApp =
+ window.location.href.includes('chat.openai.com') ||
+ window.location.href.includes('chatgpt.com') ||
+ (window as any).__OPENAI_APPS__ !== undefined ||
+ (window.parent !== window &&
+ (window.parent.location.href.includes('chat.openai.com') ||
+ window.parent.location.href.includes('chatgpt.com')));
+
+ this.detectionResults.isGPTApp = isGPTApp;
+ this.detectionResults.detectionDetails.gptAppDetection = {
+ detected: isGPTApp,
+ inIframe: window.parent !== window,
+ parentUrl: window.parent !== window ? window.parent.location.href : null,
+ };
+
+ return isGPTApp;
+ }
+
+ performFullDetection(): DetectionResults {
+ this.detectAIBot();
+ this.detectAIAssistedBrowser();
+ this.detectGPTApp();
+
+ return this.detectionResults;
+ }
+
+ shouldBlockTracking(): boolean {
+ return this.detectionResults.isAIBot;
+ }
+
+ getDetectionResults(): DetectionResults {
+ return this.detectionResults;
+ }
+}
+
+export const aiDetection = new AIDetection();
+
diff --git a/chatgpt-app-sample/lib/chatgpt-apps.ts b/chatgpt-app-sample/lib/chatgpt-apps.ts
new file mode 100644
index 00000000..580bef0c
--- /dev/null
+++ b/chatgpt-app-sample/lib/chatgpt-apps.ts
@@ -0,0 +1,45 @@
+declare global {
+ interface Window {
+ OpenAI?: {
+ Apps?: {
+ init: (config: { theme?: string; onAction?: (action: any) => void }) => any;
+ };
+ };
+ __OPENAI_APPS__?: boolean;
+ }
+}
+
+export const initializeChatGPTApps = (onAction?: (action: any) => void) => {
+ if (typeof window === 'undefined') return null;
+
+ if (typeof window.OpenAI !== 'undefined' && window.OpenAI.Apps) {
+ try {
+ const app = window.OpenAI.Apps.init({
+ theme: 'light',
+ onAction: onAction || (() => {}),
+ });
+
+ console.log('ChatGPT Apps SDK initialized');
+ return app;
+ } catch (error) {
+ console.error('Error initializing ChatGPT Apps SDK:', error);
+ return null;
+ }
+ }
+
+ return null;
+};
+
+export const isChatGPTApp = (): boolean => {
+ if (typeof window === 'undefined') return false;
+
+ return (
+ window.location.href.includes('chat.openai.com') ||
+ window.location.href.includes('chatgpt.com') ||
+ window.__OPENAI_APPS__ !== undefined ||
+ (window.parent !== window &&
+ (window.parent.location.href.includes('chat.openai.com') ||
+ window.parent.location.href.includes('chatgpt.com')))
+ );
+};
+
diff --git a/chatgpt-app-sample/lib/moengage.ts b/chatgpt-app-sample/lib/moengage.ts
new file mode 100644
index 00000000..f443a248
--- /dev/null
+++ b/chatgpt-app-sample/lib/moengage.ts
@@ -0,0 +1,156 @@
+declare global {
+ interface Window {
+ moe?: any;
+ Moengage?: any;
+ moeDataCenter?: string;
+ moeAppID?: string;
+ moengage_object?: {
+ initialised?: number;
+ invoked?: number;
+ };
+ moengage_q?: Array<{ f: string; a: any[] }>;
+ }
+}
+
+export interface MoEngageConfig {
+ dataCenter: string;
+ appId: string;
+ sdkVersion?: string;
+ debugLogs?: number;
+}
+
+export const initializeMoEngage = (config: MoEngageConfig) => {
+ if (typeof window === 'undefined') return;
+
+ const { dataCenter, appId, sdkVersion = '2', debugLogs = 1 } = config;
+
+ if (!dataCenter || !dataCenter.match(/^dc_[0-9]+$/)) {
+ console.error('Data center has not been passed correctly.');
+ return;
+ }
+
+ if (
+ window.moengage_object &&
+ ((window.moengage_object.initialised && window.moengage_object.initialised > 0) ||
+ (window.moengage_object.invoked && window.moengage_object.invoked > 0))
+ ) {
+ console.error('MoEngage Web SDK initialised multiple times.');
+ return;
+ }
+
+ window.moeDataCenter = dataCenter;
+ window.moeAppID = appId;
+
+ const script = document.createElement('script');
+ script.async = true;
+ script.src = `https://js.moengage.com/staging/versions/5.02.45/sdk.js`;
+ script.onload = () => {
+ if (window.moe && typeof window.moe === 'function') {
+ window.Moengage = window.moe({
+ app_id: appId,
+ cluster: dataCenter.toUpperCase(),
+ debug_logs: debugLogs,
+ });
+ } else if (window.moengage_object) {
+ window.Moengage = window.moengage_object;
+ }
+ };
+ script.onerror = () => {
+ console.error('Moengage Web SDK loading failed.');
+ };
+
+ document.head.appendChild(script);
+};
+
+export const isMoEngageReady = (): boolean => {
+ if (typeof window === 'undefined') return false;
+ return typeof window.Moengage !== 'undefined' && window.Moengage !== null;
+};
+
+export const identifyUser = (userData: {
+ uid?: string;
+ u_fn?: string;
+ u_em?: string;
+ u_mb?: string;
+ [key: string]: any;
+}) => {
+ if (!isMoEngageReady()) {
+ console.warn('MoEngage SDK not initialized');
+ return;
+ }
+
+ try {
+ if (userData.uid) {
+ window.Moengage.add_unique_user_id(userData.uid);
+ }
+ if (userData.u_fn) {
+ window.Moengage.add_user_name(userData.u_fn);
+ }
+ if (userData.u_em) {
+ window.Moengage.add_email(userData.u_em);
+ }
+ if (userData.u_mb) {
+ window.Moengage.add_mobile(userData.u_mb);
+ }
+
+ window.Moengage.identifyUser(userData);
+ } catch (error) {
+ console.error('Error identifying user:', error);
+ }
+};
+
+export const trackEvent = (eventName: string, eventProperties: Record = {}) => {
+ if (!isMoEngageReady()) {
+ console.warn('MoEngage SDK not initialized');
+ return;
+ }
+
+ try {
+ window.Moengage.track_event(eventName, {
+ ...eventProperties,
+ timestamp: new Date().toISOString(),
+ });
+ } catch (error) {
+ console.error('Error tracking event:', error);
+ }
+};
+
+export const addUserAttribute = (attributes: Record) => {
+ if (!isMoEngageReady()) {
+ console.warn('MoEngage SDK not initialized');
+ return;
+ }
+
+ try {
+ window.Moengage.add_user_attribute(attributes);
+ } catch (error) {
+ console.error('Error adding user attribute:', error);
+ }
+};
+
+export const destroySession = () => {
+ if (!isMoEngageReady()) {
+ console.warn('MoEngage SDK not initialized');
+ return;
+ }
+
+ try {
+ window.Moengage.destroy_session();
+ } catch (error) {
+ console.error('Error destroying session:', error);
+ }
+};
+
+export const updateUserId = (newUserId: string) => {
+ if (!isMoEngageReady()) {
+ console.warn('MoEngage SDK not initialized');
+ return;
+ }
+
+ try {
+ window.Moengage.update_unique_user_id(newUserId);
+ } catch (error) {
+ console.error('Error updating user ID:', error);
+ }
+};
+
diff --git a/chatgpt-app-sample/next-env.d.ts b/chatgpt-app-sample/next-env.d.ts
new file mode 100644
index 00000000..40c3d680
--- /dev/null
+++ b/chatgpt-app-sample/next-env.d.ts
@@ -0,0 +1,5 @@
+///
+///
+
+// NOTE: This file should not be edited
+// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
diff --git a/chatgpt-app-sample/next.config.js b/chatgpt-app-sample/next.config.js
new file mode 100644
index 00000000..8a71348a
--- /dev/null
+++ b/chatgpt-app-sample/next.config.js
@@ -0,0 +1,38 @@
+/** @type {import('next').NextConfig} */
+const nextConfig = {
+ reactStrictMode: true,
+ swcMinify: true,
+ async headers() {
+ return [
+ {
+ source: '/.well-known/:path*',
+ headers: [
+ {
+ key: 'Access-Control-Allow-Origin',
+ value: '*',
+ },
+ {
+ key: 'Content-Type',
+ value: 'application/json',
+ },
+ ],
+ },
+ {
+ source: '/:path*',
+ headers: [
+ {
+ key: 'X-Frame-Options',
+ value: 'ALLOWALL',
+ },
+ {
+ key: 'Content-Security-Policy',
+ value: "frame-ancestors 'self' https://chat.openai.com https://chatgpt.com;",
+ },
+ ],
+ },
+ ];
+ },
+};
+
+module.exports = nextConfig;
+
diff --git a/chatgpt-app-sample/package-lock.json b/chatgpt-app-sample/package-lock.json
new file mode 100644
index 00000000..b12eb191
--- /dev/null
+++ b/chatgpt-app-sample/package-lock.json
@@ -0,0 +1,5265 @@
+{
+ "name": "moengage-chatgpt-sample-app",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "moengage-chatgpt-sample-app",
+ "version": "1.0.0",
+ "license": "MIT",
+ "dependencies": {
+ "next": "^14.0.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0"
+ },
+ "devDependencies": {
+ "@types/node": "^20.0.0",
+ "@types/react": "^18.2.0",
+ "@types/react-dom": "^18.2.0",
+ "eslint": "^8.0.0",
+ "eslint-config-next": "^14.0.0",
+ "typescript": "^5.0.0"
+ }
+ },
+ "node_modules/@emnapi/core": {
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.1.tgz",
+ "integrity": "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/wasi-threads": "1.1.0",
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@emnapi/runtime": {
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz",
+ "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@emnapi/wasi-threads": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz",
+ "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.9.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz",
+ "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/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/eslintrc": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
+ "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.6.0",
+ "globals": "^13.19.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "8.57.1",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz",
+ "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@humanwhocodes/config-array": {
+ "version": "0.13.0",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
+ "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==",
+ "deprecated": "Use @eslint/config-array instead",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@humanwhocodes/object-schema": "^2.0.3",
+ "debug": "^4.3.1",
+ "minimatch": "^3.0.5"
+ },
+ "engines": {
+ "node": ">=10.10.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/object-schema": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
+ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
+ "deprecated": "Use @eslint/object-schema instead",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/ansi-regex": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
+ "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/strip-ansi": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz",
+ "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@napi-rs/wasm-runtime": {
+ "version": "0.2.12",
+ "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz",
+ "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/core": "^1.4.3",
+ "@emnapi/runtime": "^1.4.3",
+ "@tybys/wasm-util": "^0.10.0"
+ }
+ },
+ "node_modules/@next/env": {
+ "version": "14.2.35",
+ "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.35.tgz",
+ "integrity": "sha512-DuhvCtj4t9Gwrx80dmz2F4t/zKQ4ktN8WrMwOuVzkJfBilwAwGr6v16M5eI8yCuZ63H9TTuEU09Iu2HqkzFPVQ==",
+ "license": "MIT"
+ },
+ "node_modules/@next/eslint-plugin-next": {
+ "version": "14.2.35",
+ "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.35.tgz",
+ "integrity": "sha512-Jw9A3ICz2183qSsqwi7fgq4SBPiNfmOLmTPXKvlnzstUwyvBrtySiY+8RXJweNAs9KThb1+bYhZh9XWcNOr2zQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "glob": "10.3.10"
+ }
+ },
+ "node_modules/@next/swc-darwin-arm64": {
+ "version": "14.2.33",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.33.tgz",
+ "integrity": "sha512-HqYnb6pxlsshoSTubdXKu15g3iivcbsMXg4bYpjL2iS/V6aQot+iyF4BUc2qA/J/n55YtvE4PHMKWBKGCF/+wA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-darwin-x64": {
+ "version": "14.2.33",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.33.tgz",
+ "integrity": "sha512-8HGBeAE5rX3jzKvF593XTTFg3gxeU4f+UWnswa6JPhzaR6+zblO5+fjltJWIZc4aUalqTclvN2QtTC37LxvZAA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm64-gnu": {
+ "version": "14.2.33",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.33.tgz",
+ "integrity": "sha512-JXMBka6lNNmqbkvcTtaX8Gu5by9547bukHQvPoLe9VRBx1gHwzf5tdt4AaezW85HAB3pikcvyqBToRTDA4DeLw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm64-musl": {
+ "version": "14.2.33",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.33.tgz",
+ "integrity": "sha512-Bm+QulsAItD/x6Ih8wGIMfRJy4G73tu1HJsrccPW6AfqdZd0Sfm5Imhgkgq2+kly065rYMnCOxTBvmvFY1BKfg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-x64-gnu": {
+ "version": "14.2.33",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.33.tgz",
+ "integrity": "sha512-FnFn+ZBgsVMbGDsTqo8zsnRzydvsGV8vfiWwUo1LD8FTmPTdV+otGSWKc4LJec0oSexFnCYVO4hX8P8qQKaSlg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-x64-musl": {
+ "version": "14.2.33",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.33.tgz",
+ "integrity": "sha512-345tsIWMzoXaQndUTDv1qypDRiebFxGYx9pYkhwY4hBRaOLt8UGfiWKr9FSSHs25dFIf8ZqIFaPdy5MljdoawA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-arm64-msvc": {
+ "version": "14.2.33",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.33.tgz",
+ "integrity": "sha512-nscpt0G6UCTkrT2ppnJnFsYbPDQwmum4GNXYTeoTIdsmMydSKFz9Iny2jpaRupTb+Wl298+Rh82WKzt9LCcqSQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-ia32-msvc": {
+ "version": "14.2.33",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.33.tgz",
+ "integrity": "sha512-pc9LpGNKhJ0dXQhZ5QMmYxtARwwmWLpeocFmVG5Z0DzWq5Uf0izcI8tLc+qOpqxO1PWqZ5A7J1blrUIKrIFc7Q==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-x64-msvc": {
+ "version": "14.2.33",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.33.tgz",
+ "integrity": "sha512-nOjfZMy8B94MdisuzZo9/57xuFVLHJaDj5e/xrduJp9CV2/HrfxTRH2fbyLe+K9QT41WBLUd4iXX3R7jBp0EUg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nolyfill/is-core-module": {
+ "version": "1.0.39",
+ "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz",
+ "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.4.0"
+ }
+ },
+ "node_modules/@pkgjs/parseargs": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@rtsao/scc": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz",
+ "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@rushstack/eslint-patch": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.15.0.tgz",
+ "integrity": "sha512-ojSshQPKwVvSMR8yT2L/QtUkV5SXi/IfDiJ4/8d6UbTPjiHVmxZzUAzGD8Tzks1b9+qQkZa0isUOvYObedITaw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@swc/counter": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
+ "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@swc/helpers": {
+ "version": "0.5.5",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz",
+ "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@swc/counter": "^0.1.3",
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@tybys/wasm-util": {
+ "version": "0.10.1",
+ "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz",
+ "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@types/json5": {
+ "version": "0.0.29",
+ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
+ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/node": {
+ "version": "20.19.27",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.27.tgz",
+ "integrity": "sha512-N2clP5pJhB2YnZJ3PIHFk5RkygRX5WO/5f0WC08tp0wd+sv0rsJk3MqWn3CbNmT2J505a5336jaQj4ph1AdMug==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.21.0"
+ }
+ },
+ "node_modules/@types/prop-types": {
+ "version": "15.7.15",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz",
+ "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/react": {
+ "version": "18.3.27",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.27.tgz",
+ "integrity": "sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/prop-types": "*",
+ "csstype": "^3.2.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "18.3.7",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz",
+ "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "^18.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "8.50.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.50.0.tgz",
+ "integrity": "sha512-O7QnmOXYKVtPrfYzMolrCTfkezCJS9+ljLdKW/+DCvRsc3UAz+sbH6Xcsv7p30+0OwUbeWfUDAQE0vpabZ3QLg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.10.0",
+ "@typescript-eslint/scope-manager": "8.50.0",
+ "@typescript-eslint/type-utils": "8.50.0",
+ "@typescript-eslint/utils": "8.50.0",
+ "@typescript-eslint/visitor-keys": "8.50.0",
+ "ignore": "^7.0.0",
+ "natural-compare": "^1.4.0",
+ "ts-api-utils": "^2.1.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^8.50.0",
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
+ "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "8.50.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.50.0.tgz",
+ "integrity": "sha512-6/cmF2piao+f6wSxUsJLZjck7OQsYyRtcOZS02k7XINSNlz93v6emM8WutDQSXnroG2xwYlEVHJI+cPA7CPM3Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "8.50.0",
+ "@typescript-eslint/types": "8.50.0",
+ "@typescript-eslint/typescript-estree": "8.50.0",
+ "@typescript-eslint/visitor-keys": "8.50.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/project-service": {
+ "version": "8.50.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.50.0.tgz",
+ "integrity": "sha512-Cg/nQcL1BcoTijEWyx4mkVC56r8dj44bFDvBdygifuS20f3OZCHmFbjF34DPSi07kwlFvqfv/xOLnJ5DquxSGQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/tsconfig-utils": "^8.50.0",
+ "@typescript-eslint/types": "^8.50.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "8.50.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.50.0.tgz",
+ "integrity": "sha512-xCwfuCZjhIqy7+HKxBLrDVT5q/iq7XBVBXLn57RTIIpelLtEIZHXAF/Upa3+gaCpeV1NNS5Z9A+ID6jn50VD4A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.50.0",
+ "@typescript-eslint/visitor-keys": "8.50.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/tsconfig-utils": {
+ "version": "8.50.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.50.0.tgz",
+ "integrity": "sha512-vxd3G/ybKTSlm31MOA96gqvrRGv9RJ7LGtZCn2Vrc5htA0zCDvcMqUkifcjrWNNKXHUU3WCkYOzzVSFBd0wa2w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "8.50.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.50.0.tgz",
+ "integrity": "sha512-7OciHT2lKCewR0mFoBrvZJ4AXTMe/sYOe87289WAViOocEmDjjv8MvIOT2XESuKj9jp8u3SZYUSh89QA4S1kQw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.50.0",
+ "@typescript-eslint/typescript-estree": "8.50.0",
+ "@typescript-eslint/utils": "8.50.0",
+ "debug": "^4.3.4",
+ "ts-api-utils": "^2.1.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "8.50.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.50.0.tgz",
+ "integrity": "sha512-iX1mgmGrXdANhhITbpp2QQM2fGehBse9LbTf0sidWK6yg/NE+uhV5dfU1g6EYPlcReYmkE9QLPq/2irKAmtS9w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "8.50.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.50.0.tgz",
+ "integrity": "sha512-W7SVAGBR/IX7zm1t70Yujpbk+zdPq/u4soeFSknWFdXIFuWsBGBOUu/Tn/I6KHSKvSh91OiMuaSnYp3mtPt5IQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/project-service": "8.50.0",
+ "@typescript-eslint/tsconfig-utils": "8.50.0",
+ "@typescript-eslint/types": "8.50.0",
+ "@typescript-eslint/visitor-keys": "8.50.0",
+ "debug": "^4.3.4",
+ "minimatch": "^9.0.4",
+ "semver": "^7.6.0",
+ "tinyglobby": "^0.2.15",
+ "ts-api-utils": "^2.1.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@typescript-eslint/utils": {
+ "version": "8.50.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.50.0.tgz",
+ "integrity": "sha512-87KgUXET09CRjGCi2Ejxy3PULXna63/bMYv72tCAlDJC3Yqwln0HiFJ3VJMst2+mEtNtZu5oFvX4qJGjKsnAgg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.7.0",
+ "@typescript-eslint/scope-manager": "8.50.0",
+ "@typescript-eslint/types": "8.50.0",
+ "@typescript-eslint/typescript-estree": "8.50.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "8.50.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.50.0.tgz",
+ "integrity": "sha512-Xzmnb58+Db78gT/CCj/PVCvK+zxbnsw6F+O1oheYszJbBSdEjVhQi3C/Xttzxgi/GLmpvOggRs1RFpiJ8+c34Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.50.0",
+ "eslint-visitor-keys": "^4.2.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys/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/@ungap/structured-clone": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz",
+ "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/@unrs/resolver-binding-android-arm-eabi": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz",
+ "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-android-arm64": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz",
+ "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-darwin-arm64": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz",
+ "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-darwin-x64": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz",
+ "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-freebsd-x64": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz",
+ "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz",
+ "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz",
+ "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm64-gnu": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz",
+ "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm64-musl": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz",
+ "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz",
+ "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz",
+ "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-riscv64-musl": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz",
+ "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-s390x-gnu": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz",
+ "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-x64-gnu": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz",
+ "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-x64-musl": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz",
+ "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-wasm32-wasi": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz",
+ "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==",
+ "cpu": [
+ "wasm32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@napi-rs/wasm-runtime": "^0.2.11"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@unrs/resolver-binding-win32-arm64-msvc": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz",
+ "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-win32-ia32-msvc": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz",
+ "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-win32-x64-msvc": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz",
+ "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/acorn": {
+ "version": "8.15.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
+ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true,
+ "license": "Python-2.0"
+ },
+ "node_modules/aria-query": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz",
+ "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/array-buffer-byte-length": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz",
+ "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "is-array-buffer": "^3.0.5"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-includes": {
+ "version": "3.1.9",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz",
+ "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.24.0",
+ "es-object-atoms": "^1.1.1",
+ "get-intrinsic": "^1.3.0",
+ "is-string": "^1.1.1",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.findlast": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz",
+ "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.findlastindex": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz",
+ "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.9",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "es-shim-unscopables": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flat": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz",
+ "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flatmap": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz",
+ "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.tosorted": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz",
+ "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.3",
+ "es-errors": "^1.3.0",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/arraybuffer.prototype.slice": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz",
+ "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.1",
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "is-array-buffer": "^3.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/ast-types-flow": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz",
+ "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/async-function": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz",
+ "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/available-typed-arrays": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
+ "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "possible-typed-array-names": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/axe-core": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.11.0.tgz",
+ "integrity": "sha512-ilYanEU8vxxBexpJd8cWM4ElSQq4QctCLKih0TSfjIfCQTeyH/6zVrmIJfLPrKTKJRbiG+cfnZbQIjAlJmF1jQ==",
+ "dev": true,
+ "license": "MPL-2.0",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/axobject-query": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
+ "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/busboy": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
+ "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
+ "dependencies": {
+ "streamsearch": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=10.16.0"
+ }
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
+ "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.0",
+ "es-define-property": "^1.0.0",
+ "get-intrinsic": "^1.2.4",
+ "set-function-length": "^1.2.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/call-bound": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
+ "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "get-intrinsic": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001760",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001760.tgz",
+ "integrity": "sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw==",
+ "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/client-only": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
+ "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
+ "license": "MIT"
+ },
+ "node_modules/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/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.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/damerau-levenshtein": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
+ "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==",
+ "dev": true,
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/data-view-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
+ "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/data-view-byte-length": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz",
+ "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/inspect-js"
+ }
+ },
+ "node_modules/data-view-byte-offset": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz",
+ "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/define-data-property": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/define-properties": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
+ "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.0.1",
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/es-abstract": {
+ "version": "1.24.1",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.1.tgz",
+ "integrity": "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.2",
+ "arraybuffer.prototype.slice": "^1.0.4",
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "data-view-buffer": "^1.0.2",
+ "data-view-byte-length": "^1.0.2",
+ "data-view-byte-offset": "^1.0.1",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "es-set-tostringtag": "^2.1.0",
+ "es-to-primitive": "^1.3.0",
+ "function.prototype.name": "^1.1.8",
+ "get-intrinsic": "^1.3.0",
+ "get-proto": "^1.0.1",
+ "get-symbol-description": "^1.1.0",
+ "globalthis": "^1.0.4",
+ "gopd": "^1.2.0",
+ "has-property-descriptors": "^1.0.2",
+ "has-proto": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "internal-slot": "^1.1.0",
+ "is-array-buffer": "^3.0.5",
+ "is-callable": "^1.2.7",
+ "is-data-view": "^1.0.2",
+ "is-negative-zero": "^2.0.3",
+ "is-regex": "^1.2.1",
+ "is-set": "^2.0.3",
+ "is-shared-array-buffer": "^1.0.4",
+ "is-string": "^1.1.1",
+ "is-typed-array": "^1.1.15",
+ "is-weakref": "^1.1.1",
+ "math-intrinsics": "^1.1.0",
+ "object-inspect": "^1.13.4",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.7",
+ "own-keys": "^1.0.1",
+ "regexp.prototype.flags": "^1.5.4",
+ "safe-array-concat": "^1.1.3",
+ "safe-push-apply": "^1.0.0",
+ "safe-regex-test": "^1.1.0",
+ "set-proto": "^1.0.0",
+ "stop-iteration-iterator": "^1.1.0",
+ "string.prototype.trim": "^1.2.10",
+ "string.prototype.trimend": "^1.0.9",
+ "string.prototype.trimstart": "^1.0.8",
+ "typed-array-buffer": "^1.0.3",
+ "typed-array-byte-length": "^1.0.3",
+ "typed-array-byte-offset": "^1.0.4",
+ "typed-array-length": "^1.0.7",
+ "unbox-primitive": "^1.1.0",
+ "which-typed-array": "^1.1.19"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-iterator-helpers": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.2.tgz",
+ "integrity": "sha512-BrUQ0cPTB/IwXj23HtwHjS9n7O4h9FX94b4xc5zlTHxeLgTAdzYUDyy6KdExAl9lbN5rtfe44xpjpmj9grxs5w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.24.1",
+ "es-errors": "^1.3.0",
+ "es-set-tostringtag": "^2.1.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.3.0",
+ "globalthis": "^1.0.4",
+ "gopd": "^1.2.0",
+ "has-property-descriptors": "^1.0.2",
+ "has-proto": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "internal-slot": "^1.1.0",
+ "iterator.prototype": "^1.1.5",
+ "safe-array-concat": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+ "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-shim-unscopables": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz",
+ "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-to-primitive": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz",
+ "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-callable": "^1.2.7",
+ "is-date-object": "^1.0.5",
+ "is-symbol": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "8.57.1",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz",
+ "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==",
+ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.6.1",
+ "@eslint/eslintrc": "^2.1.4",
+ "@eslint/js": "8.57.1",
+ "@humanwhocodes/config-array": "^0.13.0",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@nodelib/fs.walk": "^1.2.8",
+ "@ungap/structured-clone": "^1.2.0",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.2.2",
+ "eslint-visitor-keys": "^3.4.3",
+ "espree": "^9.6.1",
+ "esquery": "^1.4.2",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "globals": "^13.19.0",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "is-path-inside": "^3.0.3",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3",
+ "strip-ansi": "^6.0.1",
+ "text-table": "^0.2.0"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-config-next": {
+ "version": "14.2.35",
+ "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.2.35.tgz",
+ "integrity": "sha512-BpLsv01UisH193WyT/1lpHqq5iJ/Orfz9h/NOOlAmTUq4GY349PextQ62K4XpnaM9supeiEn3TaOTeQO07gURg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@next/eslint-plugin-next": "14.2.35",
+ "@rushstack/eslint-patch": "^1.3.3",
+ "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0",
+ "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0",
+ "eslint-import-resolver-node": "^0.3.6",
+ "eslint-import-resolver-typescript": "^3.5.2",
+ "eslint-plugin-import": "^2.28.1",
+ "eslint-plugin-jsx-a11y": "^6.7.1",
+ "eslint-plugin-react": "^7.33.2",
+ "eslint-plugin-react-hooks": "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705"
+ },
+ "peerDependencies": {
+ "eslint": "^7.23.0 || ^8.0.0",
+ "typescript": ">=3.3.1"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-import-resolver-node": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz",
+ "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^3.2.7",
+ "is-core-module": "^2.13.0",
+ "resolve": "^1.22.4"
+ }
+ },
+ "node_modules/eslint-import-resolver-node/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-import-resolver-typescript": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz",
+ "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@nolyfill/is-core-module": "1.0.39",
+ "debug": "^4.4.0",
+ "get-tsconfig": "^4.10.0",
+ "is-bun-module": "^2.0.0",
+ "stable-hash": "^0.0.5",
+ "tinyglobby": "^0.2.13",
+ "unrs-resolver": "^1.6.2"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint-import-resolver-typescript"
+ },
+ "peerDependencies": {
+ "eslint": "*",
+ "eslint-plugin-import": "*",
+ "eslint-plugin-import-x": "*"
+ },
+ "peerDependenciesMeta": {
+ "eslint-plugin-import": {
+ "optional": true
+ },
+ "eslint-plugin-import-x": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-module-utils": {
+ "version": "2.12.1",
+ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz",
+ "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^3.2.7"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependenciesMeta": {
+ "eslint": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-module-utils/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-plugin-import": {
+ "version": "2.32.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz",
+ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@rtsao/scc": "^1.1.0",
+ "array-includes": "^3.1.9",
+ "array.prototype.findlastindex": "^1.2.6",
+ "array.prototype.flat": "^1.3.3",
+ "array.prototype.flatmap": "^1.3.3",
+ "debug": "^3.2.7",
+ "doctrine": "^2.1.0",
+ "eslint-import-resolver-node": "^0.3.9",
+ "eslint-module-utils": "^2.12.1",
+ "hasown": "^2.0.2",
+ "is-core-module": "^2.16.1",
+ "is-glob": "^4.0.3",
+ "minimatch": "^3.1.2",
+ "object.fromentries": "^2.0.8",
+ "object.groupby": "^1.0.3",
+ "object.values": "^1.2.1",
+ "semver": "^6.3.1",
+ "string.prototype.trimend": "^1.0.9",
+ "tsconfig-paths": "^3.15.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/eslint-plugin-jsx-a11y": {
+ "version": "6.10.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz",
+ "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "aria-query": "^5.3.2",
+ "array-includes": "^3.1.8",
+ "array.prototype.flatmap": "^1.3.2",
+ "ast-types-flow": "^0.0.8",
+ "axe-core": "^4.10.0",
+ "axobject-query": "^4.1.0",
+ "damerau-levenshtein": "^1.0.8",
+ "emoji-regex": "^9.2.2",
+ "hasown": "^2.0.2",
+ "jsx-ast-utils": "^3.3.5",
+ "language-tags": "^1.0.9",
+ "minimatch": "^3.1.2",
+ "object.fromentries": "^2.0.8",
+ "safe-regex-test": "^1.0.3",
+ "string.prototype.includes": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependencies": {
+ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9"
+ }
+ },
+ "node_modules/eslint-plugin-react": {
+ "version": "7.37.5",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz",
+ "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-includes": "^3.1.8",
+ "array.prototype.findlast": "^1.2.5",
+ "array.prototype.flatmap": "^1.3.3",
+ "array.prototype.tosorted": "^1.1.4",
+ "doctrine": "^2.1.0",
+ "es-iterator-helpers": "^1.2.1",
+ "estraverse": "^5.3.0",
+ "hasown": "^2.0.2",
+ "jsx-ast-utils": "^2.4.1 || ^3.0.0",
+ "minimatch": "^3.1.2",
+ "object.entries": "^1.1.9",
+ "object.fromentries": "^2.0.8",
+ "object.values": "^1.2.1",
+ "prop-types": "^15.8.1",
+ "resolve": "^2.0.0-next.5",
+ "semver": "^6.3.1",
+ "string.prototype.matchall": "^4.0.12",
+ "string.prototype.repeat": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7"
+ }
+ },
+ "node_modules/eslint-plugin-react-hooks": {
+ "version": "5.0.0-canary-7118f5dd7-20230705",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0-canary-7118f5dd7-20230705.tgz",
+ "integrity": "sha512-AZYbMo/NW9chdL7vk6HQzQhT+PvTAEVqWk9ziruUoW2kAOcN5qNyelv70e0F1VNQAbvutOC9oc+xfWycI9FxDw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/resolve": {
+ "version": "2.0.0-next.5",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz",
+ "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
+ "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/espree": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
+ "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "acorn": "^8.9.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
+ "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fastq": {
+ "version": "1.19.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz",
+ "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/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": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flat-cache": "^3.0.4"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/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": "3.2.0",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
+ "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.3",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
+ "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/for-each": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
+ "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-callable": "^1.2.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/foreground-child": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
+ "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "cross-spawn": "^7.0.6",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/function.prototype.name": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz",
+ "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "functions-have-names": "^1.2.3",
+ "hasown": "^2.0.2",
+ "is-callable": "^1.2.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/generator-function": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz",
+ "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/get-symbol-description": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz",
+ "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-tsconfig": {
+ "version": "4.13.0",
+ "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz",
+ "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "resolve-pkg-maps": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
+ }
+ },
+ "node_modules/glob": {
+ "version": "10.3.10",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz",
+ "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^2.3.5",
+ "minimatch": "^9.0.1",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
+ "path-scurry": "^1.10.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "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/glob/node_modules/brace-expansion": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/glob/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/globals": {
+ "version": "13.24.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
+ "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globalthis": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
+ "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-properties": "^1.2.1",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "dev": true,
+ "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"
+ },
+ "node_modules/graphemer": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/has-bigints": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz",
+ "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+ "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-proto": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz",
+ "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/internal-slot": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
+ "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "hasown": "^2.0.2",
+ "side-channel": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/is-array-buffer": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
+ "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "get-intrinsic": "^1.2.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-async-function": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz",
+ "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "async-function": "^1.0.0",
+ "call-bound": "^1.0.3",
+ "get-proto": "^1.0.1",
+ "has-tostringtag": "^1.0.2",
+ "safe-regex-test": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-bigint": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz",
+ "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-bigints": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-boolean-object": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz",
+ "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-bun-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz",
+ "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^7.7.1"
+ }
+ },
+ "node_modules/is-callable": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.16.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
+ "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-data-view": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz",
+ "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "get-intrinsic": "^1.2.6",
+ "is-typed-array": "^1.1.13"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-date-object": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz",
+ "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-finalizationregistry": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz",
+ "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-generator-function": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz",
+ "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.4",
+ "generator-function": "^2.0.0",
+ "get-proto": "^1.0.1",
+ "has-tostringtag": "^1.0.2",
+ "safe-regex-test": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-map": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
+ "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-negative-zero": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz",
+ "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-number-object": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz",
+ "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-regex": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
+ "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "gopd": "^1.2.0",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-set": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz",
+ "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-shared-array-buffer": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz",
+ "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-string": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz",
+ "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-symbol": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz",
+ "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "has-symbols": "^1.1.0",
+ "safe-regex-test": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-typed-array": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
+ "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "which-typed-array": "^1.1.16"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakmap": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
+ "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakref": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz",
+ "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakset": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz",
+ "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "get-intrinsic": "^1.2.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/iterator.prototype": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz",
+ "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.6",
+ "get-proto": "^1.0.0",
+ "has-symbols": "^1.1.0",
+ "set-function-name": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/jackspeak": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
+ "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "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==",
+ "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/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json5": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
+ "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "minimist": "^1.2.0"
+ },
+ "bin": {
+ "json5": "lib/cli.js"
+ }
+ },
+ "node_modules/jsx-ast-utils": {
+ "version": "3.3.5",
+ "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
+ "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-includes": "^3.1.6",
+ "array.prototype.flat": "^1.3.1",
+ "object.assign": "^4.1.4",
+ "object.values": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/language-subtag-registry": {
+ "version": "0.3.23",
+ "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz",
+ "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==",
+ "dev": true,
+ "license": "CC0-1.0"
+ },
+ "node_modules/language-tags": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz",
+ "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "language-subtag-registry": "^0.3.20"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "license": "MIT",
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/math-intrinsics": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/minipass": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.11",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/napi-postinstall": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz",
+ "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "napi-postinstall": "lib/cli.js"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/napi-postinstall"
+ }
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/next": {
+ "version": "14.2.35",
+ "resolved": "https://registry.npmjs.org/next/-/next-14.2.35.tgz",
+ "integrity": "sha512-KhYd2Hjt/O1/1aZVX3dCwGXM1QmOV4eNM2UTacK5gipDdPN/oHHK/4oVGy7X8GMfPMsUTUEmGlsy0EY1YGAkig==",
+ "license": "MIT",
+ "dependencies": {
+ "@next/env": "14.2.35",
+ "@swc/helpers": "0.5.5",
+ "busboy": "1.6.0",
+ "caniuse-lite": "^1.0.30001579",
+ "graceful-fs": "^4.2.11",
+ "postcss": "8.4.31",
+ "styled-jsx": "5.1.1"
+ },
+ "bin": {
+ "next": "dist/bin/next"
+ },
+ "engines": {
+ "node": ">=18.17.0"
+ },
+ "optionalDependencies": {
+ "@next/swc-darwin-arm64": "14.2.33",
+ "@next/swc-darwin-x64": "14.2.33",
+ "@next/swc-linux-arm64-gnu": "14.2.33",
+ "@next/swc-linux-arm64-musl": "14.2.33",
+ "@next/swc-linux-x64-gnu": "14.2.33",
+ "@next/swc-linux-x64-musl": "14.2.33",
+ "@next/swc-win32-arm64-msvc": "14.2.33",
+ "@next/swc-win32-ia32-msvc": "14.2.33",
+ "@next/swc-win32-x64-msvc": "14.2.33"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.1.0",
+ "@playwright/test": "^1.41.2",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "sass": "^1.3.0"
+ },
+ "peerDependenciesMeta": {
+ "@opentelemetry/api": {
+ "optional": true
+ },
+ "@playwright/test": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.13.4",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
+ "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.assign": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz",
+ "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0",
+ "has-symbols": "^1.1.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.entries": {
+ "version": "1.1.9",
+ "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz",
+ "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.fromentries": {
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz",
+ "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.groupby": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz",
+ "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.values": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz",
+ "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "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/own-keys": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz",
+ "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "get-intrinsic": "^1.2.6",
+ "object-keys": "^1.1.1",
+ "safe-push-apply": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "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/possible-typed-array-names": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
+ "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.4.31",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
+ "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.6",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.0.2"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/react": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
+ "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
+ "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.23.2"
+ },
+ "peerDependencies": {
+ "react": "^18.3.1"
+ }
+ },
+ "node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/reflect.getprototypeof": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
+ "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.9",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.7",
+ "get-proto": "^1.0.1",
+ "which-builtin-type": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/regexp.prototype.flags": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
+ "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-errors": "^1.3.0",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "set-function-name": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.22.11",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz",
+ "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-core-module": "^2.16.1",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/resolve-pkg-maps": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
+ "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
+ "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/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",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/rimraf/node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "Glob versions prior to v9 are no longer supported",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/safe-array-concat": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz",
+ "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.2",
+ "get-intrinsic": "^1.2.6",
+ "has-symbols": "^1.1.0",
+ "isarray": "^2.0.5"
+ },
+ "engines": {
+ "node": ">=0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safe-push-apply": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz",
+ "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "isarray": "^2.0.5"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safe-regex-test": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz",
+ "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "is-regex": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/scheduler": {
+ "version": "0.23.2",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
+ "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.7.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
+ "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/set-function-length": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
+ "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/set-function-name": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
+ "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
+ "functions-have-names": "^1.2.3",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/set-proto": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz",
+ "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/side-channel": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
+ "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.3",
+ "side-channel-list": "^1.0.0",
+ "side-channel-map": "^1.0.1",
+ "side-channel-weakmap": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-list": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
+ "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-map": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
+ "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-weakmap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
+ "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3",
+ "side-channel-map": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/stable-hash": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz",
+ "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/stop-iteration-iterator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz",
+ "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "internal-slot": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/streamsearch": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
+ "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/string-width-cjs": {
+ "name": "string-width",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/string-width/node_modules/ansi-regex": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
+ "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/string-width/node_modules/strip-ansi": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz",
+ "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/string.prototype.includes": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz",
+ "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/string.prototype.matchall": {
+ "version": "4.0.12",
+ "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz",
+ "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.6",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.6",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "internal-slot": "^1.1.0",
+ "regexp.prototype.flags": "^1.5.3",
+ "set-function-name": "^2.0.2",
+ "side-channel": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.repeat": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz",
+ "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.5"
+ }
+ },
+ "node_modules/string.prototype.trim": {
+ "version": "1.2.10",
+ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz",
+ "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.2",
+ "define-data-property": "^1.1.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-object-atoms": "^1.0.0",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimend": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz",
+ "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.2",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimstart": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz",
+ "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi-cjs": {
+ "name": "strip-ansi",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/styled-jsx": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz",
+ "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==",
+ "license": "MIT",
+ "dependencies": {
+ "client-only": "0.0.1"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "peerDependencies": {
+ "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0"
+ },
+ "peerDependenciesMeta": {
+ "@babel/core": {
+ "optional": true
+ },
+ "babel-plugin-macros": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/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/ts-api-utils": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
+ "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.12"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4"
+ }
+ },
+ "node_modules/tsconfig-paths": {
+ "version": "3.15.0",
+ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz",
+ "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/json5": "^0.0.29",
+ "json5": "^1.0.2",
+ "minimist": "^1.2.6",
+ "strip-bom": "^3.0.0"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+ "license": "0BSD"
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true,
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/typed-array-buffer": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
+ "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-typed-array": "^1.1.14"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/typed-array-byte-length": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz",
+ "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "for-each": "^0.3.3",
+ "gopd": "^1.2.0",
+ "has-proto": "^1.2.0",
+ "is-typed-array": "^1.1.14"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-byte-offset": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz",
+ "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.8",
+ "for-each": "^0.3.3",
+ "gopd": "^1.2.0",
+ "has-proto": "^1.2.0",
+ "is-typed-array": "^1.1.15",
+ "reflect.getprototypeof": "^1.0.9"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-length": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz",
+ "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "is-typed-array": "^1.1.13",
+ "possible-typed-array-names": "^1.0.0",
+ "reflect.getprototypeof": "^1.0.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.9.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
+ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/unbox-primitive": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
+ "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.1.0",
+ "which-boxed-primitive": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
+ "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/unrs-resolver": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz",
+ "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "dependencies": {
+ "napi-postinstall": "^0.3.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unrs-resolver"
+ },
+ "optionalDependencies": {
+ "@unrs/resolver-binding-android-arm-eabi": "1.11.1",
+ "@unrs/resolver-binding-android-arm64": "1.11.1",
+ "@unrs/resolver-binding-darwin-arm64": "1.11.1",
+ "@unrs/resolver-binding-darwin-x64": "1.11.1",
+ "@unrs/resolver-binding-freebsd-x64": "1.11.1",
+ "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1",
+ "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1",
+ "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1",
+ "@unrs/resolver-binding-linux-arm64-musl": "1.11.1",
+ "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1",
+ "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1",
+ "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1",
+ "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1",
+ "@unrs/resolver-binding-linux-x64-gnu": "1.11.1",
+ "@unrs/resolver-binding-linux-x64-musl": "1.11.1",
+ "@unrs/resolver-binding-wasm32-wasi": "1.11.1",
+ "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1",
+ "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1",
+ "@unrs/resolver-binding-win32-x64-msvc": "1.11.1"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/which-boxed-primitive": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz",
+ "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-bigint": "^1.1.0",
+ "is-boolean-object": "^1.2.1",
+ "is-number-object": "^1.1.1",
+ "is-string": "^1.1.1",
+ "is-symbol": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-builtin-type": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz",
+ "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "function.prototype.name": "^1.1.6",
+ "has-tostringtag": "^1.0.2",
+ "is-async-function": "^2.0.0",
+ "is-date-object": "^1.1.0",
+ "is-finalizationregistry": "^1.1.0",
+ "is-generator-function": "^1.0.10",
+ "is-regex": "^1.2.1",
+ "is-weakref": "^1.0.2",
+ "isarray": "^2.0.5",
+ "which-boxed-primitive": "^1.1.0",
+ "which-collection": "^1.0.2",
+ "which-typed-array": "^1.1.16"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-collection": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz",
+ "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-map": "^2.0.3",
+ "is-set": "^2.0.3",
+ "is-weakmap": "^2.0.2",
+ "is-weakset": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-typed-array": {
+ "version": "1.1.19",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz",
+ "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "for-each": "^0.3.5",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs": {
+ "name": "wrap-ansi",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-regex": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
+ "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-styles": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz",
+ "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/strip-ansi": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz",
+ "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "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==",
+ "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"
+ }
+ }
+ }
+}
diff --git a/chatgpt-app-sample/package.json b/chatgpt-app-sample/package.json
new file mode 100644
index 00000000..1ab428fd
--- /dev/null
+++ b/chatgpt-app-sample/package.json
@@ -0,0 +1,37 @@
+{
+ "name": "moengage-chatgpt-sample-app",
+ "version": "1.0.0",
+ "description": "Sample application with MoEngage WebSDK integration for ChatGPT Apps",
+ "private": true,
+ "scripts": {
+ "dev": "next dev -p 4000",
+ "build": "next build",
+ "start": "next start -p 4000",
+ "lint": "next lint"
+ },
+ "dependencies": {
+ "next": "^14.0.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0"
+ },
+ "devDependencies": {
+ "@types/node": "^20.0.0",
+ "@types/react": "^18.2.0",
+ "@types/react-dom": "^18.2.0",
+ "eslint": "^8.0.0",
+ "eslint-config-next": "^14.0.0",
+ "typescript": "^5.0.0"
+ },
+ "keywords": [
+ "moengage",
+ "chatgpt",
+ "openai",
+ "analytics",
+ "tracking",
+ "ai-detection",
+ "nextjs",
+ "react"
+ ],
+ "author": "MoEngage",
+ "license": "MIT"
+}
diff --git a/chatgpt-app-sample/public/.well-known/openai-apps.json b/chatgpt-app-sample/public/.well-known/openai-apps.json
new file mode 100644
index 00000000..55595cb0
--- /dev/null
+++ b/chatgpt-app-sample/public/.well-known/openai-apps.json
@@ -0,0 +1,59 @@
+{
+ "name": "MoEngage Sample App",
+ "description": "Sample application with MoEngage WebSDK integration for ChatGPT Apps",
+ "version": "1.0.0",
+ "author": "MoEngage",
+ "homepage_url": "https://your-domain.com",
+ "widgetCSP": {
+ "connect_domains": [
+ "https://api-01.moengage.com",
+ "https://api-02.moengage.com",
+ "https://api-03.moengage.com",
+ "https://api-04.moengage.com",
+ "https://api-05.moengage.com",
+ "https://api-06.moengage.com",
+ "https://api-07.moengage.com",
+ "https://api-08.moengage.com",
+ "https://api-09.moengage.com",
+ "https://api-10.moengage.com",
+ "https://api-11.moengage.com",
+ "https://api-12.moengage.com",
+ "https://api-13.moengage.com",
+ "https://api-14.moengage.com",
+ "https://api-15.moengage.com",
+ "https://api-16.moengage.com",
+ "https://api-17.moengage.com",
+ "https://api-18.moengage.com",
+ "https://api-19.moengage.com",
+ "https://api-20.moengage.com"
+ ],
+ "resource_domains": [
+ "https://cdn.moengage.com",
+ "https://sdk-01.moengage.com",
+ "https://sdk-02.moengage.com",
+ "https://sdk-03.moengage.com",
+ "https://sdk-04.moengage.com",
+ "https://sdk-05.moengage.com",
+ "https://sdk-06.moengage.com",
+ "https://sdk-07.moengage.com",
+ "https://sdk-08.moengage.com",
+ "https://sdk-09.moengage.com",
+ "https://sdk-10.moengage.com",
+ "https://sdk-11.moengage.com",
+ "https://sdk-12.moengage.com",
+ "https://sdk-13.moengage.com",
+ "https://sdk-14.moengage.com",
+ "https://sdk-15.moengage.com",
+ "https://sdk-16.moengage.com",
+ "https://sdk-17.moengage.com",
+ "https://sdk-18.moengage.com",
+ "https://sdk-19.moengage.com",
+ "https://sdk-20.moengage.com"
+ ]
+ },
+ "permissions": [
+ "user_data",
+ "analytics"
+ ]
+}
+
diff --git a/chatgpt-app-sample/public/.well-known/openapi.yaml b/chatgpt-app-sample/public/.well-known/openapi.yaml
new file mode 100644
index 00000000..d7effcc6
--- /dev/null
+++ b/chatgpt-app-sample/public/.well-known/openapi.yaml
@@ -0,0 +1,21 @@
+openapi: 3.0.0
+info:
+ title: Hotel Booking API
+ version: 1.0.0
+ description: API for searching and booking hotels through ChatGPT
+servers:
+ - url: https://your-app.vercel.app
+ description: Production server
+paths:
+ /:
+ get:
+ summary: Hotel booking interface
+ description: Main interface for hotel search and booking
+ responses:
+ '200':
+ description: HTML page with hotel booking interface
+ content:
+ text/html:
+ schema:
+ type: string
+
diff --git a/chatgpt-app-sample/public/ai-plugin.json b/chatgpt-app-sample/public/ai-plugin.json
new file mode 100644
index 00000000..a09de3ec
--- /dev/null
+++ b/chatgpt-app-sample/public/ai-plugin.json
@@ -0,0 +1,18 @@
+{
+ "schema_version": "v1",
+ "name_for_human": "Hotel Booking",
+ "name_for_model": "hotel_booking",
+ "description_for_human": "Search and book hotels with real-time availability and pricing. Powered by MoEngage analytics.",
+ "description_for_model": "A hotel booking service that allows users to search for hotels by destination, check-in/check-out dates, and number of guests. Users can view hotel details, compare prices, and complete bookings. All interactions are tracked via MoEngage for analytics.",
+ "auth": {
+ "type": "none"
+ },
+ "api": {
+ "type": "openapi",
+ "url": "https://your-app.vercel.app/.well-known/openapi.yaml"
+ },
+ "logo_url": "https://your-app.vercel.app/logo.png",
+ "contact_email": "support@example.com",
+ "legal_info_url": "https://your-app.vercel.app/legal"
+}
+
diff --git a/chatgpt-app-sample/tsconfig.json b/chatgpt-app-sample/tsconfig.json
new file mode 100644
index 00000000..067ed5f7
--- /dev/null
+++ b/chatgpt-app-sample/tsconfig.json
@@ -0,0 +1,29 @@
+{
+ "compilerOptions": {
+ "target": "es5",
+ "lib": ["dom", "dom.iterable", "esnext"],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "forceConsistentCasingInFileNames": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "bundler",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "incremental": true,
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ],
+ "paths": {
+ "@/*": ["./*"]
+ }
+ },
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
+ "exclude": ["node_modules"]
+}
+
diff --git a/chatgpt-app-sample/vercel.json b/chatgpt-app-sample/vercel.json
new file mode 100644
index 00000000..a7878fbe
--- /dev/null
+++ b/chatgpt-app-sample/vercel.json
@@ -0,0 +1,13 @@
+{
+ "version": 2,
+ "buildCommand": "npm run build",
+ "devCommand": "npm run dev",
+ "installCommand": "npm install",
+ "framework": "nextjs",
+ "regions": ["iad1"],
+ "env": {
+ "NEXT_PUBLIC_MOENGAGE_DATACENTER": "@moengage-datacenter",
+ "NEXT_PUBLIC_MOENGAGE_APP_ID": "@moengage-app-id"
+ }
+}
+
diff --git a/lib/moengage.ts b/lib/moengage.ts
new file mode 100644
index 00000000..b5bc298f
--- /dev/null
+++ b/lib/moengage.ts
@@ -0,0 +1,155 @@
+declare global {
+ interface Window {
+ moe?: any;
+ Moengage?: any;
+ moeDataCenter?: string;
+ moeAppID?: string;
+ moengage_object?: {
+ initialised?: number;
+ invoked?: number;
+ };
+ moengage_q?: Array<{ f: string; a: any[] }>;
+ }
+}
+
+export interface MoEngageConfig {
+ dataCenter: string;
+ appId: string;
+ sdkVersion?: string;
+ debugLogs?: number;
+}
+
+export const initializeMoEngage = (config: MoEngageConfig) => {
+ if (typeof window === 'undefined') return;
+
+ const { dataCenter, appId, sdkVersion = '2', debugLogs = 1 } = config;
+
+ if (!dataCenter || !dataCenter.match(/^dc_[0-9]+$/)) {
+ console.error('Data center has not been passed correctly.');
+ return;
+ }
+
+ if (
+ window.moengage_object &&
+ ((window.moengage_object.initialised && window.moengage_object.initialised > 0) ||
+ (window.moengage_object.invoked && window.moengage_object.invoked > 0))
+ ) {
+ console.error('MoEngage Web SDK initialised multiple times.');
+ return;
+ }
+
+ window.moeDataCenter = dataCenter;
+ window.moeAppID = appId;
+
+ const script = document.createElement('script');
+ script.async = true;
+ // script.src = `https://cdn.moengage.com/release/${dataCenter}/versions/${sdkVersion}/moe_webSdk.min.latest.js`;
+ script.src = `https://js.moengage.com/staging/versions/5.02.45/sdk.js`;
+ script.onload = () => {
+ if (window.moe) {
+ window.Moengage = window.moe({
+ app_id: appId,
+ cluster: dataCenter.toUpperCase(),
+ debug_logs: debugLogs,
+ });
+ }
+ };
+ script.onerror = () => {
+ console.error('Moengage Web SDK loading failed.');
+ };
+
+ document.head.appendChild(script);
+};
+
+export const isMoEngageReady = (): boolean => {
+ if (typeof window === 'undefined') return false;
+ return typeof window.Moengage !== 'undefined' && window.Moengage !== null;
+};
+
+export const identifyUser = (userData: {
+ uid?: string;
+ u_fn?: string;
+ u_em?: string;
+ u_mb?: string;
+ [key: string]: any;
+}) => {
+ if (!isMoEngageReady()) {
+ console.warn('MoEngage SDK not initialized');
+ return;
+ }
+
+ try {
+ if (userData.uid) {
+ window.Moengage.add_unique_user_id(userData.uid);
+ }
+ if (userData.u_fn) {
+ window.Moengage.add_user_name(userData.u_fn);
+ }
+ if (userData.u_em) {
+ window.Moengage.add_email(userData.u_em);
+ }
+ if (userData.u_mb) {
+ window.Moengage.add_mobile(userData.u_mb);
+ }
+
+ window.Moengage.identifyUser(userData);
+ } catch (error) {
+ console.error('Error identifying user:', error);
+ }
+};
+
+export const trackEvent = (eventName: string, eventProperties: Record = {}) => {
+ if (!isMoEngageReady()) {
+ console.warn('MoEngage SDK not initialized');
+ return;
+ }
+
+ try {
+ window.Moengage.track_event(eventName, {
+ ...eventProperties,
+ timestamp: new Date().toISOString(),
+ });
+ } catch (error) {
+ console.error('Error tracking event:', error);
+ }
+};
+
+export const addUserAttribute = (attributes: Record) => {
+ if (!isMoEngageReady()) {
+ console.warn('MoEngage SDK not initialized');
+ return;
+ }
+
+ try {
+ window.Moengage.add_user_attribute(attributes);
+ } catch (error) {
+ console.error('Error adding user attribute:', error);
+ }
+};
+
+export const destroySession = () => {
+ if (!isMoEngageReady()) {
+ console.warn('MoEngage SDK not initialized');
+ return;
+ }
+
+ try {
+ window.Moengage.destroy_session();
+ } catch (error) {
+ console.error('Error destroying session:', error);
+ }
+};
+
+export const updateUserId = (newUserId: string) => {
+ if (!isMoEngageReady()) {
+ console.warn('MoEngage SDK not initialized');
+ return;
+ }
+
+ try {
+ window.Moengage.update_unique_user_id(newUserId);
+ } catch (error) {
+ console.error('Error updating user ID:', error);
+ }
+};
+