diff --git a/test-apps/.gitignore b/test-apps/.gitignore new file mode 100644 index 0000000..34c104c --- /dev/null +++ b/test-apps/.gitignore @@ -0,0 +1,127 @@ +# Dependencies +node_modules/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +# Build outputs +dist/ +build/ +*.tsbuildinfo + +# Environment files +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# IDE files +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS generated files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# Logs +logs/ +*.log + +# Runtime data +pids/ +*.pid +*.seed +*.pid.lock + +# Coverage directory used by tools like istanbul +coverage/ +*.lcov + +# nyc test coverage +.nyc_output/ + +# Dependency directories +jspm_packages/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next + +# Nuxt.js build / generate output +.nuxt + +# Storybook build outputs +.out +.storybook-out + +# Temporary folders +tmp/ +temp/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +# Capacitor specific +android/app/build/ +android/build/ +android/.gradle/ +android/gradle/ +android/gradlew +android/gradlew.bat +android/local.properties +android/capacitor.settings.gradle +android/variables.gradle + +# iOS specific (for future use) +ios/App/build/ +ios/App/Pods/ +ios/App/public/ +ios/App/capacitor.config.json +ios/App/capacitor.plugins.json + +# Electron specific (for future use) +electron/dist/ +electron/build/ + +# Test coverage +coverage/ + +# Misc +*.tgz +*.tar.gz diff --git a/test-apps/EMULATOR_TROUBLESHOOTING.md b/test-apps/EMULATOR_TROUBLESHOOTING.md deleted file mode 100644 index d410cba..0000000 --- a/test-apps/EMULATOR_TROUBLESHOOTING.md +++ /dev/null @@ -1,280 +0,0 @@ -# Android Emulator GPU Troubleshooting Guide - -## Overview - -This guide helps resolve GPU binding issues when running Android emulators on Linux systems with NVIDIA graphics cards. The most common issue is when the emulator detects the NVIDIA GPU for Vulkan but still binds OpenGL rendering to the Intel iGPU. - -## Problem Diagnosis - -### GPU Binding Issues - -#### Symptoms -- Emulator runs but feels sluggish -- NVIDIA GPU shows low utilization in `nvidia-smi` -- Emulator banner shows Intel graphics in OpenGL renderer: - ``` - OpenGL Renderer=[Android Emulator OpenGL ES Translator (Mesa Intel(R) Graphics (RPL-S))] - ``` -- Vulkan detection works but OpenGL compositing uses Intel - -#### Root Cause -The emulator detects your NVIDIA GPU for Vulkan (`Selecting Vulkan device: NVIDIA GeForce RTX 4060...`) but the window/compositor path still binds to your Intel iGPU. Frames get decoded via gfxstream/Vulkan but final GL presentation rides the Intel driver. - -### Network Connectivity Issues - -#### Symptoms -- Play Services ANRs and timeouts -- "API failed to connect while resuming" errors -- `GmsClientSupervisor ... Timeout...` messages -- `Phenotype registration failed` errors -- NetworkMonitor shows hard failures: - - `ECONNREFUSED` on DNS lookups - - `UnknownHostException` for `www.google.com` / `connectivitycheck.gstatic.com` - - `[100 WIFI] validation failed` - -#### Root Cause -The emulator has no working internet/DNS connectivity, causing Google apps to stall and ANR. This is often caused by: -- DNS resolution failures -- VPN/killswitch blocking emulator traffic -- Firewall rules blocking outbound connections -- Corrupted network state from previous sessions - -## Solution Strategies - -### 1. Network Connectivity Fixes (Priority) - -If experiencing ANRs and Play Services failures, address network issues first: - -#### Quick Network Fix -```bash -cd test-apps -./launch-emulator-network-fix.sh -``` - -#### Verify Network Status -```bash -cd test-apps -./verify-emulator-network.sh -``` - -#### Manual Network Verification -```bash -# Check airplane mode -adb -e shell settings get global airplane_mode_on - -# Check network interfaces -adb -e shell ip addr; adb -e shell ip route - -# Test DNS resolution -adb -e shell ping -c1 8.8.8.8 -adb -e shell ping -c1 connectivitycheck.gstatic.com -``` - -#### Clear Play Services Cache -```bash -adb -e shell pm clear com.google.android.gms -adb -e shell pm clear com.android.vending -``` - -### 2. GPU Binding Solutions - -Use the enhanced launch script with all NVIDIA offloading variables: - -```bash -cd test-apps -./launch-emulator-gpu.sh -``` - -**What each variable does:** -- `__NV_PRIME_RENDER_OFFLOAD=1` + `__GLX_VENDOR_LIBRARY_NAME=nvidia`: Offload GL to NVIDIA -- `__VK_LAYER_NV_optimus=NVIDIA_only` + `VK_ICD_FILENAMES=...nvidia_icd.json`: Make Vulkan loader pick NVIDIA -- `DRI_PRIME=1`: Belt-and-suspenders in mixed Mesa/NVIDIA setups -- `QT_QPA_PLATFORM=xcb`: Avoids Wayland/Qt oddities -- `-no-snapshot-load`: Prevents flaky snapshots from different configs - -### 2. Alternative GPU Modes - -If the primary solution still binds to Intel, try these alternatives: - -#### Pure OpenGL Mode -```bash -cd test-apps -./launch-emulator-opengl.sh -``` -- Removes `-feature Vulkan` to avoid mixed VK+GL path -- Forces pure OpenGL rendering on NVIDIA -- Good when Vulkan+OpenGL mixed mode causes issues - -#### ANGLE Mode -```bash -cd test-apps -./launch-emulator-angle.sh -``` -- Uses ANGLE (Almost Native Graphics Layer Engine) -- Better NVIDIA compatibility on Linux -- More stable rendering pipeline - -#### Mesa Fallback -```bash -cd test-apps -./launch-emulator-mesa.sh -``` -- Software rendering as last resort -- Use only for stability testing -- More CPU intensive but very stable - -### 3. Manual Launch Commands - -If scripts don't work, use these manual commands: - -#### Enhanced GPU Launch -```bash -QT_QPA_PLATFORM=xcb \ -__NV_PRIME_RENDER_OFFLOAD=1 \ -__GLX_VENDOR_LIBRARY_NAME=nvidia \ -__VK_LAYER_NV_optimus=NVIDIA_only \ -VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/nvidia_icd.json \ -DRI_PRIME=1 \ -emulator -avd TimeSafari_Emulator \ - -gpu host \ - -feature Vulkan \ - -accel on \ - -no-boot-anim \ - -no-snapshot-load -``` - -#### Pure OpenGL -```bash -QT_QPA_PLATFORM=xcb \ -__NV_PRIME_RENDER_OFFLOAD=1 \ -__GLX_VENDOR_LIBRARY_NAME=nvidia \ -DRI_PRIME=1 \ -emulator -avd TimeSafari_Emulator \ - -gpu host \ - -accel on \ - -no-boot-anim -``` - -#### ANGLE Mode -```bash -QT_QPA_PLATFORM=xcb \ -__NV_PRIME_RENDER_OFFLOAD=1 \ -__GLX_VENDOR_LIBRARY_NAME=nvidia \ -DRI_PRIME=1 \ -emulator -avd TimeSafari_Emulator \ - -gpu angle_indirect \ - -accel on \ - -no-boot-anim -``` - -## Verification - -### Check GPU Binding -After launching, check the emulator banner for: -- ✅ **Good**: `OpenGL Vendor=Google (NVIDIA)` or GL translator running atop NVIDIA -- ❌ **Bad**: `(Mesa Intel)` or Intel graphics in renderer - -### Monitor GPU Usage -```bash -# Real-time GPU utilization -nvidia-smi dmon -s u - -# Check emulator process specifically -watch -n1 "nvidia-smi --query-compute-apps=pid,process_name,used_memory --format=csv,noheader | grep qemu" -``` - -You should see non-zero GPU utilization/memory for the emulator process. - -## Additional Optimizations - -### Clean Snapshots -Snapshots made with different configs can cause issues: -```bash -# Delete snapshots for clean state -rm -rf ~/.android/avd/TimeSafari_Emulator.avd/snapshots/ -``` - -### Fix ADB Issues -"Device offline" after boot is common with snapshots: -```bash -adb kill-server && adb start-server -adb -e wait-for-device -``` - -### Disable Unnecessary Features -Save CPU, reduce log spam, and prevent hangs: -```bash -emulator -avd TimeSafari_Emulator \ - -gpu host -accel on -no-boot-anim \ - -feature -Bluetooth -camera-back none -camera-front none -no-audio -``` - -**Key Benefits:** -- `-feature -Bluetooth`: Prevents Bluetooth-related hangs and ANRs -- `-camera-back none -camera-front none`: Disables camera hardware -- `-no-audio`: Disables audio system (saves resources) - -### CPU/RAM Configuration -Keep your existing settings: -```bash -emulator -avd TimeSafari_Emulator \ - -cores 6 -memory 4096 \ - -gpu host -accel on -no-boot-anim -``` - -## Troubleshooting Checklist - -### Before Launch -- [ ] NVIDIA drivers installed and working -- [ ] Vulkan ICD file exists: `/usr/share/vulkan/icd.d/nvidia_icd.json` -- [ ] AVD exists and is properly configured -- [ ] Android SDK and emulator in PATH - -### After Launch -- [ ] Check emulator banner for correct GPU binding -- [ ] Monitor `nvidia-smi` for GPU utilization -- [ ] Verify ADB connection with `adb devices` -- [ ] Test app installation and functionality - -### If Still Having Issues -- [ ] Try different GPU modes (OpenGL, ANGLE, Mesa) -- [ ] Clean snapshots and restart -- [ ] Check system logs for GPU errors -- [ ] Verify NVIDIA driver compatibility -- [ ] Consider software rendering for stability testing - -## Performance Expectations - -### Hardware Acceleration (NVIDIA) -- **GPU Utilization**: 20-60% during normal use -- **Memory Usage**: 500MB-2GB GPU memory -- **UI Responsiveness**: Smooth, 60fps target -- **Startup Time**: 30-60 seconds - -### Software Rendering (Mesa) -- **CPU Usage**: 50-80% on all cores -- **Memory Usage**: 1-4GB system RAM -- **UI Responsiveness**: Slower, 30fps typical -- **Startup Time**: 60-120 seconds - -## System Requirements - -### Minimum -- **CPU**: 4 cores, 2.5GHz+ -- **RAM**: 8GB system, 4GB for emulator -- **GPU**: Any with OpenGL 3.0+ support -- **Storage**: 10GB free space - -### Recommended -- **CPU**: 6+ cores, 3.0GHz+ -- **RAM**: 16GB system, 6GB for emulator -- **GPU**: NVIDIA GTX 1060+ or equivalent -- **Storage**: 20GB free space, SSD preferred - -## Support - -If you continue experiencing issues: -1. Check the [Android Emulator documentation](https://developer.android.com/studio/run/emulator) -2. Review [NVIDIA Linux driver documentation](https://docs.nvidia.com/driver/) -3. Test with different AVD configurations -4. Consider using physical Android devices for testing diff --git a/test-apps/README.md b/test-apps/README.md deleted file mode 100644 index 4113885..0000000 --- a/test-apps/README.md +++ /dev/null @@ -1,326 +0,0 @@ -# TimeSafari Test Apps Setup Guide - -## Overview - -This guide creates minimal Capacitor test apps for validating the TimeSafari Daily Notification Plugin integration across all target platforms. The test apps demonstrate TimeSafari's community-building features, Endorser.ch API integration, and notification patterns. - -## Directory Structure - -``` -test-apps/ -├── android-test/ # Android test app -├── ios-test/ # iOS test app -├── electron-test/ # Electron test app -├── test-api/ # TimeSafari Test API server -├── shared/ # Shared configuration and utilities -│ └── config-loader.ts # Configuration loader and mock services -├── config/ # Configuration files -│ └── timesafari-config.json -├── setup-android.sh # Android setup script -├── setup-ios.sh # iOS setup script -├── setup-electron.sh # Electron setup script -├── check-environment.sh # Environment verification -├── SETUP_GUIDE.md # Enhanced setup guide -└── README.md # This guide -``` - -## Prerequisites - -- Node.js 18+ -- Capacitor CLI: `npm install -g @capacitor/cli` -- Android Studio (for Android) -- Xcode (for iOS) -- Platform-specific SDKs -- Understanding of TimeSafari's community-building purpose -- Familiarity with Endorser.ch API patterns - -## Quick Start - -### Option 1: Automated Setup (Recommended) -```bash -# Navigate to test-apps directory first -cd test-apps - -# Setup all platforms (run from test-apps directory) -./setup-android.sh -./setup-ios.sh -./setup-electron.sh -``` - -**⚠️ Important**: Run setup scripts from the `test-apps` directory, not from individual platform directories. - -### Option 2: Manual Setup -See [Enhanced Setup Guide](SETUP_GUIDE.md) for detailed manual setup instructions and troubleshooting. - -### Prerequisites Check -```bash -# Check your environment before setup -./check-environment.sh -``` - -**Required Software**: -- **Node.js 18+**: Required for all platforms -- **Android Studio**: Required for Android testing -- **Xcode**: Required for iOS testing (macOS only) -- **No additional requirements**: For Electron testing - -## Test App Features - -Each test app includes comprehensive UI patterns and testing capabilities: - -### **Core Testing Features** -- **TimeSafari Configuration**: Test community-focused notification settings -- **Generic Polling Interface**: Test new structured request/response polling system -- **Endorser.ch API Integration**: Test real API patterns with pagination -- **Community Notification Scheduling**: Test offers, projects, people, and items notifications -- **Static Daily Reminders**: Test simple daily notifications without network content -- **Performance Monitoring**: Metrics collection and display -- **Error Handling**: Comprehensive error testing -- **Debug Information**: Platform-specific debug data - -### **Enhanced UI Components** -- **Permission Management**: Request dialogs, status displays, settings integration -- **Configuration Panels**: Settings toggles, time pickers, content type selection -- **Status Dashboards**: Real-time monitoring with performance metrics -- **Platform-Specific Features**: - - **Android**: Battery optimization, exact alarm permissions, reboot recovery - - **iOS**: Background app refresh, rolling window management, BGTaskScheduler - - **Electron**: Service worker status, push notifications, IPC communication -- **Error Handling UI**: User-friendly error displays with retry mechanisms -- **Testing Tools**: Test notification panels, debug info, log export - -### **UI Design Features** -- **Responsive Design**: Mobile-first approach with touch-friendly interfaces -- **Accessibility**: WCAG 2.1 AA compliance with keyboard navigation -- **Platform Native**: Material Design (Android), Human Interface Guidelines (iOS) -- **Progressive Disclosure**: Essential features first, advanced options on demand -- **Real-time Updates**: Live status monitoring and performance metrics - -## TimeSafari Test API Server - -A comprehensive REST API server (`test-api/`) simulates Endorser.ch API endpoints for testing the plugin's TimeSafari-specific functionality: - -### Quick Start -```bash -# Start the TimeSafari Test API server -cd test-apps/test-api -npm install -npm start - -# Test the API -npm run demo -``` - -### Key Features -- **Endorser.ch API Simulation**: Mock endpoints for offers, projects, and pagination -- **TimeSafari Notification Bundle**: Single route for bundled notifications -- **Community Analytics**: Analytics endpoint for community events -- **Pagination Support**: Full afterId/beforeId pagination testing -- **ETag Support**: HTTP caching with conditional requests -- **Error Simulation**: Test various error scenarios -- **Metrics**: Monitor API usage and performance -- **CORS Enabled**: Cross-origin requests supported - -### API Endpoints - -#### Endorser.ch API Endpoints -- `GET /api/v2/report/offers` - Get offers to person -- `GET /api/v2/report/offersToPlansOwnedByMe` - Get offers to user's projects -- `POST /api/v2/report/plansLastUpdatedBetween` - Get changes to starred projects - -#### TimeSafari API Endpoints -- `GET /api/v2/report/notifications/bundle` - Get bundled notifications -- `POST /api/analytics/community-events` - Send community analytics - -#### Legacy Endpoints -- `GET /health` - Health check -- `GET /api/content/:slotId` - Get notification content -- `GET /api/metrics` - API metrics - -### Platform-Specific URLs -- **Web/Electron**: `http://localhost:3001` -- **Android Emulator**: `http://10.0.2.2:3001` -- **iOS Simulator**: `http://localhost:3001` -- **Physical Devices**: `http://[YOUR_IP]:3001` - -## Platform-Specific Testing - -### Android Test App -- **TimeSafari Configuration**: Test community notification settings -- **Generic Polling Interface**: Test structured request/response polling with Android WorkManager -- **Endorser.ch API Integration**: Test parallel API requests -- **Exact Alarm Status**: Check permission and capability -- **Permission Requests**: Test exact alarm permission flow -- **Performance Metrics**: Monitor Android-specific optimizations -- **Reboot Recovery**: Validate system restart handling -- **Enhanced UI**: Permission dialogs, battery optimization, exact alarm management -- **Status Dashboard**: Real-time monitoring with Android-specific metrics -- **Error Handling**: User-friendly error displays with retry mechanisms - -### iOS Test App -- **TimeSafari Configuration**: Test iOS community features -- **Generic Polling Interface**: Test structured request/response polling with iOS BGTaskScheduler -- **Rolling Window**: Test notification limit management -- **Endorser.ch API Integration**: Test pagination patterns -- **Background Tasks**: Validate BGTaskScheduler integration -- **Performance Metrics**: Monitor iOS-specific optimizations -- **Memory Management**: Test object pooling and cleanup -- **Enhanced UI**: Background refresh dialogs, rolling window controls, BGTaskScheduler status -- **Status Dashboard**: Real-time monitoring with iOS-specific metrics -- **Error Handling**: User-friendly error displays with retry mechanisms - -### Electron Test App -- **TimeSafari Configuration**: Test Electron community features -- **Mock Implementations**: Test web platform compatibility -- **Endorser.ch API Integration**: Test API patterns -- **IPC Communication**: Validate Electron-specific APIs -- **Development Workflow**: Test plugin integration -- **Debug Information**: Platform-specific status display -- **Enhanced UI**: Service worker status, push notification setup, debug information -- **Status Dashboard**: Real-time monitoring with Electron-specific metrics -- **Error Handling**: User-friendly error displays with retry mechanisms - -## Running the Test Apps - -### Android -```bash -cd android-test -npm run dev # Web development server -npx cap open android # Open in Android Studio -npx cap run android # Run on device/emulator -``` - -#### High-Performance Emulator Launch (Linux + NVIDIA) - -For optimal GPU acceleration on Linux systems: - -```bash -# Launch with GPU acceleration and performance optimizations -QT_QPA_PLATFORM=xcb \ -__NV_PRIME_RENDER_OFFLOAD=1 \ -__GLX_VENDOR_LIBRARY_NAME=nvidia \ -__VK_LAYER_NV_optimus=NVIDIA_only \ -VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/nvidia_icd.json \ -DRI_PRIME=1 \ -emulator -avd TimeSafari_Emulator \ - -gpu host \ - -feature Vulkan \ - -accel on \ - -no-boot-anim \ - -no-snapshot-load -``` - -**Benefits:** -- Hardware GPU acceleration for smoother UI -- Vulkan graphics API support -- Faster startup (no boot animation) -- Clean state (no snapshot loading) -- Optimized for NVIDIA graphics cards - -#### Alternative GPU Modes - -If you experience GPU binding issues, try these alternatives: - -```bash -# Pure OpenGL mode (no Vulkan) -./launch-emulator-opengl.sh - -# ANGLE mode (better NVIDIA compatibility) -./launch-emulator-angle.sh - -# Mesa fallback (software rendering) -./launch-emulator-mesa.sh -``` - -**Troubleshooting:** -- See [EMULATOR_TROUBLESHOOTING.md](./EMULATOR_TROUBLESHOOTING.md) for detailed GPU binding solutions -- Check emulator banner for correct GPU binding -- Monitor GPU usage with `nvidia-smi dmon -s u` - -### iOS -```bash -cd ios-test -npm run dev # Web development server -npx cap open ios # Open in Xcode -npx cap run ios # Run on device/simulator -``` - -### Electron -```bash -cd electron-test -npm start # Run Electron app -npm run dev # Run in development mode -``` - -## Testing Checklist - -### Core Functionality -- [ ] TimeSafari configuration works -- [ ] Generic polling interface functions properly -- [ ] Community notification scheduling succeeds -- [ ] Endorser.ch API integration functions properly -- [ ] Error handling functions properly -- [ ] Performance metrics are accurate - -### Enhanced UI Testing -- [ ] Permission management dialogs display correctly -- [ ] Settings panels save and load configuration -- [ ] Status dashboards show real-time data -- [ ] Error handling UI displays user-friendly messages -- [ ] Platform-specific features work as expected -- [ ] Responsive design works on different screen sizes -- [ ] Accessibility features function properly - -### Platform-Specific -- [ ] Android exact alarm permissions, battery optimization, reboot recovery -- [ ] iOS rolling window management, background refresh, BGTaskScheduler -- [ ] Electron mock implementations, service worker, push notifications -- [ ] Cross-platform API consistency - -### TimeSafari Integration -- [ ] Plugin loads without errors -- [ ] Configuration persists across sessions -- [ ] Endorser.ch API pagination works -- [ ] Community notification types process correctly -- [ ] Performance optimizations active -- [ ] Debug information accessible - -## Troubleshooting - -### Common Issues -1. **"Unknown command: cap"** → Install Capacitor CLI: `npm install -g @capacitor/cli` -2. **"android platform has not been added yet"** → Run `npx cap add android` first -3. **Build failures** → Check Node.js version (18+) and clear cache: `npm cache clean --force` -4. **Platform errors** → Verify platform-specific SDKs are installed -5. **API connection errors** → Ensure test API server is running on port 3001 - -### Quick Fixes -```bash -# Check environment -./check-environment.sh - -# Reinstall dependencies -rm -rf node_modules && npm install - -# Clear Capacitor cache -npx cap clean - -# Re-sync platforms -npx cap sync - -# Restart test API server -cd test-api && npm start -``` - -### Detailed Help -See [Enhanced Setup Guide](SETUP_GUIDE.md) for comprehensive troubleshooting and platform-specific solutions. - -## Next Steps - -1. **Run Setup Scripts**: Execute platform-specific setup -2. **Start Test API Server**: Run the TimeSafari Test API server -3. **Test Core Features**: Validate basic TimeSafari functionality -4. **Test Platform Features**: Verify platform-specific capabilities -5. **Test Endorser.ch Integration**: Validate API patterns and pagination -6. **Integration Testing**: Test with actual plugin implementation -7. **Performance Validation**: Monitor metrics and optimizations diff --git a/test-apps/SETUP_GUIDE.md b/test-apps/SETUP_GUIDE.md deleted file mode 100644 index e311bfa..0000000 --- a/test-apps/SETUP_GUIDE.md +++ /dev/null @@ -1,384 +0,0 @@ -# Enhanced Test Apps Setup Guide - -## Overview - -This guide creates minimal Capacitor test apps for validating the Daily Notification Plugin across all target platforms with robust error handling and clear troubleshooting. - -## Prerequisites - -### Required Software -- **Node.js 18+**: Download from [nodejs.org](https://nodejs.org/) -- **npm**: Comes with Node.js -- **Git**: For version control - -### Platform-Specific Requirements - -#### Android -- **Android Studio**: Download from [developer.android.com/studio](https://developer.android.com/studio) -- **Android SDK**: Installed via Android Studio -- **Java Development Kit (JDK)**: Version 11 or higher - -#### iOS (macOS only) -- **Xcode**: Install from Mac App Store -- **Xcode Command Line Tools**: `xcode-select --install` -- **iOS Simulator**: Included with Xcode - -#### Electron -- **No additional requirements**: Works on any platform with Node.js - -## Quick Start - -### Option 1: Automated Setup (Recommended) - -```bash -# Navigate to test-apps directory -cd test-apps - -# Setup all platforms (run from test-apps directory) -./setup-android.sh -./setup-ios.sh -./setup-electron.sh -``` - -### Option 2: Manual Setup - -#### Android Manual Setup -```bash -cd test-apps/android-test - -# Install dependencies -npm install - -# Install Capacitor CLI globally -npm install -g @capacitor/cli - -# Initialize Capacitor -npx cap init "Daily Notification Android Test" "com.timesafari.dailynotification.androidtest" - -# Add Android platform -npx cap add android - -# Build web assets -npm run build - -# Sync to native -npx cap sync android -``` - -#### iOS Manual Setup -```bash -cd test-apps/ios-test - -# Install dependencies -npm install - -# Install Capacitor CLI globally -npm install -g @capacitor/cli - -# Initialize Capacitor -npx cap init "Daily Notification iOS Test" "com.timesafari.dailynotification.iostest" - -# Add iOS platform -npx cap add ios - -# Build web assets -npm run build - -# Sync to native -npx cap sync ios -``` - -#### Electron Manual Setup -```bash -cd test-apps/electron-test - -# Install dependencies -npm install - -# Build web assets -npm run build-web -``` - -## Common Issues and Solutions - -### Issue: "Unknown command: cap" -**Solution**: Install Capacitor CLI globally -```bash -npm install -g @capacitor/cli -``` - -### Issue: "android platform has not been added yet" -**Solution**: Add the Android platform first -```bash -npx cap add android -``` - -### Issue: "Failed to add Android platform" -**Solutions**: -1. Install Android Studio and Android SDK -2. Set `ANDROID_HOME` environment variable -3. Add Android SDK tools to your PATH - -### Issue: "Failed to add iOS platform" -**Solutions**: -1. Install Xcode from Mac App Store -2. Install Xcode Command Line Tools: `xcode-select --install` -3. Ensure you're running on macOS - -### Issue: Build failures -**Solutions**: -1. Check Node.js version: `node --version` (should be 18+) -2. Clear npm cache: `npm cache clean --force` -3. Delete `node_modules` and reinstall: `rm -rf node_modules && npm install` - -## Platform-Specific Setup - -### Android Setup Verification - -```bash -# Check Android Studio installation -which studio - -# Check Android SDK -echo $ANDROID_HOME - -# Check Java -java -version -``` - -**Required Environment Variables**: -```bash -export ANDROID_HOME=/path/to/android/sdk -export PATH=$PATH:$ANDROID_HOME/tools:$ANDROID_HOME/platform-tools -``` - -### iOS Setup Verification - -```bash -# Check Xcode installation -xcodebuild -version - -# Check iOS Simulator -xcrun simctl list devices - -# Check Command Line Tools -xcode-select -p -``` - -### Electron Setup Verification - -```bash -# Check Node.js version -node --version - -# Check npm -npm --version - -# Test Electron installation -npx electron --version -``` - -## Running the Test Apps - -### Android -```bash -cd test-apps/android-test - -# Web development server (for testing) -npm run dev - -# Open in Android Studio -npx cap open android - -# Run on device/emulator -npx cap run android -``` - -#### Advanced Emulator Launch (GPU Acceleration) - -For optimal performance on Linux systems with NVIDIA graphics: - -```bash -# Launch emulator with GPU acceleration and performance tuning -QT_QPA_PLATFORM=xcb \ -__NV_PRIME_RENDER_OFFLOAD=1 \ -__GLX_VENDOR_LIBRARY_NAME=nvidia \ -__VK_LAYER_NV_optimus=NVIDIA_only \ -VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/nvidia_icd.json \ -DRI_PRIME=1 \ -emulator -avd TimeSafari_Emulator \ - -gpu host \ - -feature Vulkan \ - -accel on \ - -cores 6 \ - -memory 4096 \ - -no-boot-anim \ - -no-snapshot-load \ - -dns-server 8.8.8.8,1.1.1.1 -``` - -**Environment Variables Explained:** - -- `QT_QPA_PLATFORM=xcb`: Use X11 backend for Qt applications -- `__NV_PRIME_RENDER_OFFLOAD=1`: Enable NVIDIA GPU offloading -- `__GLX_VENDOR_LIBRARY_NAME=nvidia`: Use NVIDIA OpenGL library -- `__VK_LAYER_NV_optimus=NVIDIA_only`: Force NVIDIA Vulkan layer -- `VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/nvidia_icd.json`: Specify NVIDIA Vulkan driver -- `DRI_PRIME=1`: Enable DRI Prime for GPU selection - -**Emulator Flags Explained:** - -- `-gpu host`: Use host GPU for hardware acceleration -- `-feature Vulkan`: Enable Vulkan graphics API support -- `-accel on`: Enable hardware acceleration -- `-cores 6`: Allocate 6 CPU cores to emulator -- `-memory 4096`: Allocate 4GB RAM to emulator -- `-no-boot-anim`: Skip boot animation for faster startup -- `-no-snapshot-load`: Don't load snapshots for clean state -- `-dns-server 8.8.8.8,1.1.1.1`: Use explicit DNS servers -- `-feature -Bluetooth`: Disable Bluetooth to prevent hangs - -#### Alternative GPU Modes - -If you experience GPU binding issues (OpenGL using Intel iGPU instead of NVIDIA), try these alternative launch scripts: - -```bash -# Pure OpenGL mode (no Vulkan) -./launch-emulator-opengl.sh - -# ANGLE mode (better NVIDIA compatibility) -./launch-emulator-angle.sh - -# Mesa fallback (software rendering) -./launch-emulator-mesa.sh -``` - -**Troubleshooting GPU Issues:** - -- Check emulator banner for `OpenGL Vendor=Google (NVIDIA)` -- Monitor GPU usage: `nvidia-smi dmon -s u` -- See [EMULATOR_TROUBLESHOOTING.md](./EMULATOR_TROUBLESHOOTING.md) for detailed solutions - -### iOS - -```bash -cd test-apps/ios-test - -# Web development server (for testing) -npm run dev - -# Open in Xcode -npx cap open ios - -# Run on device/simulator -npx cap run ios -``` - -### Electron - -```bash -cd test-apps/electron-test - -# Run Electron app -npm start - -# Run in development mode -npm run dev - -# Build and run -npm run electron -``` - -## Testing Workflow - -### 1. Web Testing (Recommended First) - -```bash -# Test each platform's web version first -cd test-apps/android-test && npm run dev -cd test-apps/ios-test && npm run dev -cd test-apps/electron-test && npm start -``` - -### 2. Native Testing - -```bash -# After web testing succeeds, test native platforms -cd test-apps/android-test && npx cap run android -cd test-apps/ios-test && npx cap run ios -``` - -### 3. Integration Testing - -- Test plugin configuration -- Test notification scheduling -- Test platform-specific features -- Test error handling -- Test performance metrics - -## Troubleshooting Checklist - -### General Issues - -- [ ] Node.js 18+ installed -- [ ] npm working correctly -- [ ] Capacitor CLI installed globally -- [ ] Dependencies installed (`npm install`) - -### Android Issues - -- [ ] Android Studio installed -- [ ] Android SDK configured -- [ ] `ANDROID_HOME` environment variable set -- [ ] Java JDK 11+ installed -- [ ] Android platform added (`npx cap add android`) - -### iOS Issues - -- [ ] Xcode installed (macOS only) -- [ ] Xcode Command Line Tools installed -- [ ] iOS Simulator available -- [ ] iOS platform added (`npx cap add ios`) - -### Electron Issues - -- [ ] Node.js working correctly -- [ ] Dependencies installed -- [ ] Web assets built (`npm run build-web`) - -## Development Tips - -### Web Development - -- Use `npm run dev` for hot reloading -- Test plugin APIs in browser console -- Use browser dev tools for debugging - -### Native Development - -- Use `npx cap sync` after making changes -- Check native logs for detailed errors -- Test on both physical devices and simulators - -### Debugging - -- Check console logs for errors -- Use `npx cap doctor` to diagnose issues -- Verify platform-specific requirements - -## Next Steps - -1. **Run Setup Scripts**: Execute platform-specific setup -2. **Test Web Versions**: Validate basic functionality -3. **Test Native Platforms**: Verify platform-specific features -4. **Integration Testing**: Test with actual plugin implementation -5. **Performance Validation**: Monitor metrics and optimizations - -## Support - -If you encounter issues not covered in this guide: - -1. Check the [Capacitor Documentation](https://capacitorjs.com/docs) -2. Verify platform-specific requirements -3. Check console logs for detailed error messages -4. Ensure all prerequisites are properly installed diff --git a/test-apps/android-test/.eslintrc.cjs b/test-apps/android-test/.eslintrc.cjs deleted file mode 100644 index b7406d6..0000000 --- a/test-apps/android-test/.eslintrc.cjs +++ /dev/null @@ -1,20 +0,0 @@ -/* eslint-env node */ -require('@rushstack/eslint-patch/modern-module-resolution') - -module.exports = { - root: true, - 'extends': [ - 'plugin:vue/vue3-essential', - 'eslint:recommended', - '@vue/eslint-config-typescript' - ], - parserOptions: { - ecmaVersion: 'latest' - }, - rules: { - 'vue/multi-word-component-names': 'off', - '@typescript-eslint/no-unused-vars': ['error', { 'argsIgnorePattern': '^_' }], - 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', - 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off' - } -} diff --git a/test-apps/android-test/.gitignore b/test-apps/android-test/.gitignore deleted file mode 100644 index a217c10..0000000 --- a/test-apps/android-test/.gitignore +++ /dev/null @@ -1,105 +0,0 @@ -# Dependencies -node_modules/ -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# Build outputs -dist/ -build/ -*.tsbuildinfo - -# Capacitor -android/ -ios/ -.capacitor/ - -# IDE and editor files -.vscode/ -.idea/ -*.swp -*.swo -*~ - -# OS generated files -.DS_Store -.DS_Store? -._* -.Spotlight-V100 -.Trashes -ehthumbs.db -Thumbs.db - -# Logs -logs -*.log - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Coverage directory used by tools like istanbul -coverage/ -*.lcov - -# nyc test coverage -.nyc_output - -# Dependency directories -jspm_packages/ - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Microbundle cache -.rpt2_cache/ -.rts2_cache_cjs/ -.rts2_cache_es/ -.rts2_cache_umd/ - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -.env -.env.test -.env.local -.env.development.local -.env.test.local -.env.production.local - -# parcel-bundler cache (https://parceljs.org/) -.cache -.parcel-cache - -# next.js build output -.next - -# nuxt.js build output -.nuxt - -# vuepress build output -.vuepress/dist - -# Serverless directories -.serverless/ - -# FuseBox cache -.fusebox/ - -# DynamoDB Local files -.dynamodb/ - -# TernJS port file -.tern-port diff --git a/test-apps/android-test/GRADLE_TROUBLESHOOTING.md b/test-apps/android-test/GRADLE_TROUBLESHOOTING.md deleted file mode 100644 index 7ca40aa..0000000 --- a/test-apps/android-test/GRADLE_TROUBLESHOOTING.md +++ /dev/null @@ -1,160 +0,0 @@ -# Android Test App Gradle Sync Troubleshooting - -## Problem: Gradle Sync Failure - -**Error Message:** -``` -Unable to find method 'org.gradle.api.artifacts.Dependency org.gradle.api.artifacts.dsl.DependencyHandler.module(java.lang.Object)' -``` - -## Root Cause - -The Android test app was using **Gradle 9.0-milestone-1** (pre-release) with **Android Gradle Plugin 8.0.0**, causing version incompatibility issues. - -## Solution Applied - -### 1. Updated Gradle Version -**File:** `android/gradle/wrapper/gradle-wrapper.properties` -```properties -# Changed from: -distributionUrl=https\://services.gradle.org/distributions/gradle-9.0-milestone-1-bin.zip - -# To: -distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip -``` - -### 2. Updated Android Gradle Plugin -**File:** `android/build.gradle` -```gradle -// Changed from: -classpath 'com.android.tools.build:gradle:8.0.0' - -// To: -classpath 'com.android.tools.build:gradle:8.13.0' -``` - -### 3. Updated Google Services Plugin -```gradle -// Changed from: -classpath 'com.google.gms:google-services:4.3.15' - -// To: -classpath 'com.google.gms:google-services:4.4.0' -``` - -### 4. Updated AndroidX Dependencies -**File:** `android/variables.gradle` -```gradle -// Updated to latest stable versions: -androidxAppCompatVersion = '1.7.1' // was 1.6.1 -androidxActivityVersion = '1.8.2' // was 1.7.0 -androidxCoreVersion = '1.12.0' // was 1.10.0 -androidxFragmentVersion = '1.6.2' // was 1.5.6 -coreSplashScreenVersion = '1.0.1' // was 1.0.0 -androidxWebkitVersion = '1.8.0' // was 1.6.1 -compileSdkVersion = 34 // was 33 -targetSdkVersion = 34 // was 33 -``` - -## Manual Fix Steps - -If you encounter this issue again: - -### Step 1: Clean Gradle Cache -```bash -cd test-apps/android-test/android -./gradlew clean -./gradlew --stop -``` - -### Step 2: Clear Gradle Wrapper Cache -```bash -rm -rf ~/.gradle/wrapper/dists/gradle-9.0-milestone-1* -``` - -### Step 3: Re-sync Project -In Android Studio: -1. Click **File** → **Sync Project with Gradle Files** -2. Or click the **Sync Now** link in the error banner - -### Step 4: If Still Failing -```bash -# Delete all Gradle caches -rm -rf ~/.gradle/caches -rm -rf ~/.gradle/wrapper - -# Re-download Gradle -cd test-apps/android-test/android -./gradlew wrapper --gradle-version 8.4 -``` - -## Prevention - -### Use Stable Versions -Always use stable, tested version combinations: - -| Android Gradle Plugin | Gradle Version | Status | -|----------------------|----------------|---------| -| 8.13.0 | 8.13 | ✅ Latest Stable | -| 8.1.4 | 8.4 | ✅ Stable | -| 8.0.0 | 8.0 | ✅ Stable | -| 7.4.2 | 7.5 | ✅ Stable | -| 8.0.0 | 9.0-milestone-1 | ❌ Incompatible | - -### Version Compatibility Check -- **Android Gradle Plugin 8.13.0** requires **Gradle 8.0+** -- **Gradle 8.13** is the latest stable version -- **AndroidX AppCompat 1.7.1** is the latest stable version -- Avoid pre-release versions in production - -## Additional Troubleshooting - -### If Sync Still Fails - -1. **Check Java Version** - ```bash - java -version - # Should be Java 17+ for AGP 8.1.4 - ``` - -2. **Check Android SDK** - ```bash - echo $ANDROID_HOME - # Should point to Android SDK location - ``` - -3. **Check Local Properties** - ```bash - # Verify android/local.properties exists - cat test-apps/android-test/android/local.properties - ``` - -4. **Recreate Project** - ```bash - cd test-apps/android-test - rm -rf android/ - npx cap add android - ``` - -## Success Indicators - -After applying the fix, you should see: -- ✅ **Gradle sync successful** -- ✅ **No red error banners** -- ✅ **Build.gradle file opens without errors** -- ✅ **Project structure loads correctly** - -## Next Steps - -Once Gradle sync is successful: -1. **Build the project**: `./gradlew build` -2. **Run on device**: `npx cap run android` -3. **Test plugin functionality**: Use the test API server -4. **Validate notifications**: Test the Daily Notification Plugin - -## Related Issues - -- **Build failures**: Usually resolved by Gradle sync fix -- **Plugin not found**: Check Capacitor plugin installation -- **Permission errors**: Verify Android manifest permissions -- **Runtime crashes**: Check plugin initialization code diff --git a/test-apps/android-test/README.md b/test-apps/android-test/README.md deleted file mode 100644 index bacca5e..0000000 --- a/test-apps/android-test/README.md +++ /dev/null @@ -1,329 +0,0 @@ -# Daily Notification Test App - Vue 3 - -A modern Vue 3 + Vite + Capacitor test application for the Daily Notification Plugin, built with vue-facing-decorator for TypeScript class-based components. - -## 🚀 Features - -- **Vue 3** with Composition API and TypeScript -- **Vite** for fast development and building -- **vue-facing-decorator** for class-based components -- **Pinia** for state management -- **Vue Router** for navigation -- **Capacitor** for native Android functionality -- **Modern UI** with glassmorphism design -- **Responsive** design for mobile and desktop - -## 📱 App Structure - -``` -src/ -├── components/ # Reusable Vue components -│ ├── cards/ # Card components (ActionCard, StatusCard, etc.) -│ ├── items/ # List item components -│ ├── layout/ # Layout components (Header, Footer) -│ └── ui/ # UI components (Loading, Error, etc.) -├── stores/ # Pinia stores -│ ├── app.ts # Global app state -│ └── notifications.ts # Notification management -├── views/ # Page components -│ ├── HomeView.vue # Dashboard -│ ├── ScheduleView.vue # Schedule notifications -│ ├── NotificationsView.vue # Manage notifications -│ ├── StatusView.vue # System status -│ ├── HistoryView.vue # Notification history -│ └── SettingsView.vue # App settings -├── router/ # Vue Router configuration -├── types/ # TypeScript type definitions -└── utils/ # Utility functions -``` - -## 🛠️ Development - -### Prerequisites - -- Node.js 18+ -- npm or yarn -- Android Studio (for Android development) -- Capacitor CLI - -### Installation - -```bash -# Install dependencies -npm install - -# Start development server -npm run dev - -# Build for production -npm run build - -# Type checking -npm run type-check - -# Linting -npm run lint -``` - -### Android Development - -```bash -# Sync with Capacitor -npm run sync - -# Open Android Studio -npm run open - -# Run on Android device/emulator -npm run android -``` - -## 🎨 UI Components - -### Class-Based Components - -All components use vue-facing-decorator for TypeScript class-based syntax: - -```typescript -@Component({ - components: { - ChildComponent - } -}) -export default class MyComponent extends Vue { - @Prop() title!: string - - private data = ref('') - - get computedValue(): string { - return this.data.value.toUpperCase() - } - - private handleClick(): void { - // Handle click - } -} -``` - -### State Management - -Uses Pinia stores for reactive state management: - -```typescript -// stores/notifications.ts -export const useNotificationsStore = defineStore('notifications', () => { - const scheduledNotifications = ref([]) - - async function scheduleNotification(options: ScheduleOptions): Promise { - // Schedule logic - } - - return { - scheduledNotifications, - scheduleNotification - } -}) -``` - -## 📊 Features - -### Dashboard (Home) -- Quick action cards -- System status overview -- Next scheduled notification -- Recent activity feed - -### Schedule Notifications -- Time picker -- Title and message inputs -- Sound and priority options -- URL support for deep linking -- Quick schedule presets - -### Notification Management -- View all scheduled notifications -- Cancel notifications -- Status indicators - -### System Status -- Permission checks -- Channel status -- Exact alarm settings -- Platform information -- Test notification functionality - -### History -- Delivered notification history -- Click and dismiss tracking -- Time-based filtering - -## 🔧 Configuration - -### Capacitor Config - -```typescript -// capacitor.config.ts -const config: CapacitorConfig = { - appId: 'com.timesafari.dailynotification.androidtest', - appName: 'Daily Notification Test - Vue 3', - webDir: 'dist', - plugins: { - DailyNotification: { - storage: 'shared', - ttlSeconds: 1800, - prefetchLeadMinutes: 15, - enableETagSupport: true, - enableErrorHandling: true, - enablePerformanceOptimization: true - } - } -} -``` - -### Vite Config - -```typescript -// vite.config.ts -export default defineConfig({ - plugins: [vue()], - build: { - outDir: 'dist', - sourcemap: true - }, - resolve: { - alias: { - '@': resolve(__dirname, 'src') - } - } -}) -``` - -## 🎯 Testing the Plugin - -1. **Start Development Server** - ```bash - npm run dev - ``` - -2. **Build and Sync** - ```bash - npm run build - npm run sync - ``` - -3. **Run on Android** - ```bash - npm run android - ``` - -4. **Test Features** - - Schedule notifications - - Check system status - - View notification history - - Test clickable notifications - -## 📱 Native Features - -- **Notification Scheduling** - Schedule daily notifications -- **Permission Management** - Check and request permissions -- **Status Monitoring** - Real-time system status -- **Deep Linking** - URL support in notifications -- **Background Processing** - WorkManager integration - -## 🎨 Design System - -### Colors -- Primary: Linear gradient (purple to blue) -- Success: #4caf50 -- Warning: #ff9800 -- Error: #f44336 -- Info: #2196f3 - -### Typography -- Headers: Bold, white with text-shadow -- Body: Regular, rgba white -- Code: Courier New monospace - -### Components -- Glassmorphism design with backdrop-filter -- Rounded corners (8px, 12px, 16px) -- Smooth transitions and hover effects -- Responsive grid layouts - -## 🚀 Production Build - -```bash -# Build for production -npm run build - -# Preview production build -npm run preview - -# Sync with Capacitor -npm run sync - -# Build Android APK -npm run android -``` - -## 📝 Scripts - -- `npm run dev` - Start development server -- `npm run build` - Build for production -- `npm run preview` - Preview production build -- `npm run android` - Run on Android -- `npm run sync` - Sync with Capacitor -- `npm run open` - Open Android Studio -- `npm run lint` - Run ESLint -- `npm run type-check` - TypeScript type checking - -## 🔍 Debugging - -### Vue DevTools -Install Vue DevTools browser extension for component inspection. - -### Capacitor Logs -```bash -# Android logs -adb logcat | grep -i "daily\|notification" - -# Capacitor logs -npx cap run android --livereload --external -``` - -### TypeScript -Enable strict mode in `tsconfig.json` for better type checking. - -## 📚 Dependencies - -### Core -- Vue 3.4+ -- Vite 5.0+ -- TypeScript 5.3+ -- Capacitor 5.0+ - -### UI & State -- vue-facing-decorator 3.0+ -- Pinia 2.1+ -- Vue Router 4.2+ - -### Development -- ESLint + TypeScript configs -- Vue TSC for type checking -- Modern module resolution - -## 🤝 Contributing - -1. Follow Vue 3 + TypeScript best practices -2. Use vue-facing-decorator for class components -3. Maintain responsive design -4. Add proper TypeScript types -5. Test on both web and Android - -## 📄 License - -MIT License - see LICENSE file for details. - ---- - -**Built with ❤️ using Vue 3 + Vite + Capacitor** diff --git a/test-apps/android-test/capacitor.config.ts b/test-apps/android-test/capacitor.config.ts deleted file mode 100644 index 2e0d5c3..0000000 --- a/test-apps/android-test/capacitor.config.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { CapacitorConfig } from '@capacitor/cli'; - -const config: CapacitorConfig = { - appId: 'com.timesafari.dailynotification.androidtest', - appName: 'Daily Notification Test - Vue 3', - webDir: 'dist', - server: { - androidScheme: 'https' - }, - plugins: { - DailyNotification: { - storage: 'shared', - ttlSeconds: 1800, - prefetchLeadMinutes: 15, - enableETagSupport: true, - enableErrorHandling: true, - enablePerformanceOptimization: true - } - }, - android: { - allowMixedContent: true - } -}; - -export default config; diff --git a/test-apps/android-test/env.d.ts b/test-apps/android-test/env.d.ts deleted file mode 100644 index 9e0a952..0000000 --- a/test-apps/android-test/env.d.ts +++ /dev/null @@ -1,90 +0,0 @@ -/** - * Environment Type Declarations - * - * @author Matthew Raymer - * @version 1.0.0 - */ - -/// - -declare module '*.vue' { - import type { DefineComponent } from 'vue' - const component: DefineComponent<{}, {}, any> - export default component -} - -// Capacitor plugin declarations -declare global { - interface Window { - DailyNotification: { - scheduleDailyNotification: (options: { - time: string - title?: string - body?: string - sound?: boolean - priority?: string - url?: string - }) => Promise - - scheduleDailyReminder: (options: { - id: string - title: string - body: string - time: string - sound?: boolean - vibration?: boolean - priority?: string - repeatDaily?: boolean - timezone?: string - }) => Promise - - cancelDailyReminder: (options: { - reminderId: string - }) => Promise - - updateDailyReminder: (options: { - reminderId: string - title?: string - body?: string - time?: string - sound?: boolean - vibration?: boolean - priority?: string - repeatDaily?: boolean - timezone?: string - }) => Promise - - getLastNotification: () => Promise<{ - id: string - title: string - body: string - scheduledTime: number - deliveredAt: number - }> - - checkStatus: () => Promise<{ - canScheduleNow: boolean - postNotificationsGranted: boolean - channelEnabled: boolean - channelImportance: number - channelId: string - exactAlarmsGranted: boolean - exactAlarmsSupported: boolean - androidVersion: number - nextScheduledAt: number - }> - - checkChannelStatus: () => Promise<{ - enabled: boolean - importance: number - id: string - }> - - openChannelSettings: () => Promise - - openExactAlarmSettings: () => Promise - } - } -} - -export {} diff --git a/test-apps/android-test/index.html b/test-apps/android-test/index.html deleted file mode 100644 index 8090857..0000000 --- a/test-apps/android-test/index.html +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - Daily Notification Test - Vue 3 - - - - - - - - - - - - - - - - -
-
-
- Loading Daily Notification Test App... -
-
- - - diff --git a/test-apps/android-test/package.json b/test-apps/android-test/package.json deleted file mode 100644 index e7f4339..0000000 --- a/test-apps/android-test/package.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "name": "daily-notification-android-test", - "version": "1.0.0", - "description": "Vue 3 + Vite + Capacitor test app for Daily Notification Plugin", - "type": "module", - "scripts": { - "dev": "vite", - "build": "vite build", - "preview": "vite preview", - "android": "npx cap run android", - "sync": "npx cap sync android", - "open": "npx cap open android", - "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore", - "type-check": "vue-tsc --noEmit" - }, - "keywords": ["capacitor", "android", "notifications", "test", "vue3", "vite", "typescript"], - "author": "Matthew Raymer", - "license": "MIT", - "dependencies": { - "@capacitor/core": "^5.0.0", - "@capacitor/android": "^5.0.0", - "@capacitor/cli": "^5.0.0", - "vue": "^3.4.0", - "vue-router": "^4.2.0", - "pinia": "^2.1.0", - "vue-facing-decorator": "^3.0.0" - }, - "devDependencies": { - "@capacitor/cli": "^5.0.0", - "@types/node": "^20.0.0", - "@typescript-eslint/eslint-plugin": "^6.0.0", - "@typescript-eslint/parser": "^6.0.0", - "@vitejs/plugin-vue": "^4.5.0", - "@vue/eslint-config-typescript": "^12.0.0", - "@vue/tsconfig": "^0.5.0", - "eslint": "^8.0.0", - "eslint-plugin-vue": "^9.0.0", - "typescript": "~5.3.0", - "vite": "^5.0.0", - "vue-tsc": "^1.8.0" - } -} \ No newline at end of file diff --git a/test-apps/android-test/src/App.vue b/test-apps/android-test/src/App.vue deleted file mode 100644 index faddc3b..0000000 --- a/test-apps/android-test/src/App.vue +++ /dev/null @@ -1,147 +0,0 @@ - - - - - - - diff --git a/test-apps/android-test/src/components/cards/ActionCard.vue b/test-apps/android-test/src/components/cards/ActionCard.vue deleted file mode 100644 index e145772..0000000 --- a/test-apps/android-test/src/components/cards/ActionCard.vue +++ /dev/null @@ -1,163 +0,0 @@ - - - - - - - diff --git a/test-apps/android-test/src/components/cards/InfoCard.vue b/test-apps/android-test/src/components/cards/InfoCard.vue deleted file mode 100644 index ffe1e44..0000000 --- a/test-apps/android-test/src/components/cards/InfoCard.vue +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - diff --git a/test-apps/android-test/src/components/cards/NotificationCard.vue b/test-apps/android-test/src/components/cards/NotificationCard.vue deleted file mode 100644 index 49ff77c..0000000 --- a/test-apps/android-test/src/components/cards/NotificationCard.vue +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - diff --git a/test-apps/android-test/src/components/cards/StatusCard.vue b/test-apps/android-test/src/components/cards/StatusCard.vue deleted file mode 100644 index 8104b6e..0000000 --- a/test-apps/android-test/src/components/cards/StatusCard.vue +++ /dev/null @@ -1,264 +0,0 @@ - - - - - - - diff --git a/test-apps/android-test/src/components/items/ActivityItem.vue b/test-apps/android-test/src/components/items/ActivityItem.vue deleted file mode 100644 index 4451b82..0000000 --- a/test-apps/android-test/src/components/items/ActivityItem.vue +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - diff --git a/test-apps/android-test/src/components/items/HistoryItem.vue b/test-apps/android-test/src/components/items/HistoryItem.vue deleted file mode 100644 index 1d62b02..0000000 --- a/test-apps/android-test/src/components/items/HistoryItem.vue +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - diff --git a/test-apps/android-test/src/components/items/StatusItem.vue b/test-apps/android-test/src/components/items/StatusItem.vue deleted file mode 100644 index c644c0d..0000000 --- a/test-apps/android-test/src/components/items/StatusItem.vue +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - diff --git a/test-apps/android-test/src/components/layout/AppFooter.vue b/test-apps/android-test/src/components/layout/AppFooter.vue deleted file mode 100644 index da13d58..0000000 --- a/test-apps/android-test/src/components/layout/AppFooter.vue +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - diff --git a/test-apps/android-test/src/components/layout/AppHeader.vue b/test-apps/android-test/src/components/layout/AppHeader.vue deleted file mode 100644 index ed9fd91..0000000 --- a/test-apps/android-test/src/components/layout/AppHeader.vue +++ /dev/null @@ -1,239 +0,0 @@ - - - - - - - diff --git a/test-apps/android-test/src/main.ts b/test-apps/android-test/src/main.ts deleted file mode 100644 index dfec0c1..0000000 --- a/test-apps/android-test/src/main.ts +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Main Application Entry Point - * - * Vue 3 + TypeScript + Capacitor + vue-facing-decorator setup - * - * @author Matthew Raymer - * @version 1.0.0 - */ - -import { createApp } from 'vue' -import { createPinia } from 'pinia' -import { Capacitor } from '@capacitor/core' -import App from './App.vue' -import router from './router' - -// Create Vue app instance -const app = createApp(App) - -// Configure Pinia for state management -const pinia = createPinia() -app.use(pinia) - -// Configure Vue Router -app.use(router) - -// Global error handler for Capacitor -app.config.errorHandler = (err, _instance, info) => { - console.error('Vue Error:', err, info) - if (Capacitor.isNativePlatform()) { - // Log to native platform - console.error('Native Platform Error:', err) - } -} - -// Mount the app -app.mount('#app') - -// Log platform information -console.log('🚀 Daily Notification Test App Started') -console.log('📱 Platform:', Capacitor.getPlatform()) -console.log('🔧 Native Platform:', Capacitor.isNativePlatform()) -console.log('🌐 Web Platform:', Capacitor.isPluginAvailable('App')) diff --git a/test-apps/android-test/src/router/index.ts b/test-apps/android-test/src/router/index.ts deleted file mode 100644 index 935d8e6..0000000 --- a/test-apps/android-test/src/router/index.ts +++ /dev/null @@ -1,109 +0,0 @@ -/** - * Vue Router Configuration - * - * @author Matthew Raymer - * @version 1.0.0 - */ - -import { createRouter, createWebHistory } from 'vue-router' -import type { RouteRecordRaw } from 'vue-router' - -const routes: RouteRecordRaw[] = [ - { - path: '/', - name: 'Home', - component: () => import('@/views/HomeView.vue'), - meta: { - title: 'Daily Notification Test', - requiresAuth: false - } - }, - { - path: '/notifications', - name: 'Notifications', - component: () => import('@/views/NotificationsView.vue'), - meta: { - title: 'Notification Management', - requiresAuth: false - } - }, - { - path: '/schedule', - name: 'Schedule', - component: () => import('@/views/ScheduleView.vue'), - meta: { - title: 'Schedule Notification', - requiresAuth: false - } - }, - { - path: '/status', - name: 'Status', - component: () => import('@/views/StatusView.vue'), - meta: { - title: 'System Status', - requiresAuth: false - } - }, - { - path: '/history', - name: 'History', - component: () => import('@/views/HistoryView.vue'), - meta: { - title: 'Notification History', - requiresAuth: false - } - }, - { - path: '/logs', - name: 'Logs', - component: () => import('@/views/LogsView.vue'), - meta: { - title: 'Android Logs', - requiresAuth: false - } - }, - { - path: '/settings', - name: 'Settings', - component: () => import('@/views/SettingsView.vue'), - meta: { - title: 'Settings', - requiresAuth: false - } - }, - { - path: '/:pathMatch(.*)*', - name: 'NotFound', - component: () => import('@/views/NotFoundView.vue'), - meta: { - title: 'Page Not Found', - requiresAuth: false - } - } -] - -const router = createRouter({ - history: createWebHistory(), - routes -}) - -// Global navigation guards -router.beforeEach((to, from, next) => { - // Set page title - if (to.meta?.title) { - document.title = `${to.meta.title} - Daily Notification Test` - } - - // Add loading state - console.log(`🔄 Navigating from ${String(from.name) || 'unknown'} to ${String(to.name) || 'unknown'}`) - - next() -}) - -router.afterEach((to) => { - // Clear any previous errors on successful navigation - console.log(`✅ Navigation completed: ${String(to.name) || 'unknown'}`) -}) - -export default router diff --git a/test-apps/android-test/src/stores/notifications.ts b/test-apps/android-test/src/stores/notifications.ts deleted file mode 100644 index 52a7a0a..0000000 --- a/test-apps/android-test/src/stores/notifications.ts +++ /dev/null @@ -1,299 +0,0 @@ -/** - * Notifications Store - Notification Management State - * - * Pinia store for managing notification scheduling, status, and history - * - * @author Matthew Raymer - * @version 1.0.0 - */ - -import { defineStore } from 'pinia' -import { ref, computed } from 'vue' -import { Capacitor } from '@capacitor/core' - -export interface ScheduledNotification { - id: string - title: string - body: string - scheduledTime: number - deliveredAt?: number - status: 'scheduled' | 'delivered' | 'cancelled' -} - -export interface NotificationHistory { - id: string - title: string - body: string - scheduledTime: number - deliveredAt: number - clicked: boolean - dismissed: boolean -} - -export const useNotificationsStore = defineStore('notifications', () => { - // State - const scheduledNotifications = ref([]) - const notificationHistory = ref([]) - const isScheduling = ref(false) - const lastError = ref(null) - - // Getters - const hasScheduledNotifications = computed(() => - scheduledNotifications.value.length > 0 - ) - - const nextNotification = computed(() => { - const future = scheduledNotifications.value - .filter(n => n.status === 'scheduled' && n.scheduledTime > Date.now()) - .sort((a, b) => a.scheduledTime - b.scheduledTime) - return future.length > 0 ? future[0] : null - }) - - const notificationCount = computed(() => - scheduledNotifications.value.length - ) - - // Actions - async function scheduleNotification(options: { - time: string - title?: string - body?: string - sound?: boolean - priority?: string - url?: string - }): Promise { - if (!Capacitor.isNativePlatform()) { - throw new Error('DailyNotification plugin only available on native platforms') - } - - if (!window.DailyNotification) { - throw new Error('DailyNotification plugin not loaded. Please restart the app.') - } - - try { - isScheduling.value = true - lastError.value = null - - await window.DailyNotification.scheduleDailyNotification(options) - - // Add to local state (we'll get the actual ID from the plugin) - const notification: ScheduledNotification = { - id: `temp-${Date.now()}`, - title: options.title || 'Daily Update', - body: options.body || 'Your daily notification is ready', - scheduledTime: parseTimeToTimestamp(options.time), - status: 'scheduled' - } - - scheduledNotifications.value.push(notification) - - console.log('✅ Notification scheduled successfully') - - } catch (error) { - const errorMessage = (error as Error).message - lastError.value = errorMessage - console.error('❌ Failed to schedule notification:', errorMessage) - throw error - } finally { - isScheduling.value = false - } - } - - async function scheduleReminder(options: { - id: string - title: string - body: string - time: string - sound?: boolean - vibration?: boolean - priority?: string - repeatDaily?: boolean - timezone?: string - }): Promise { - if (!Capacitor.isNativePlatform()) { - throw new Error('DailyNotification plugin only available on native platforms') - } - - if (!window.DailyNotification) { - throw new Error('DailyNotification plugin not loaded. Please restart the app.') - } - - try { - isScheduling.value = true - lastError.value = null - - await window.DailyNotification.scheduleDailyReminder(options) - - // Add to local state - const notification: ScheduledNotification = { - id: options.id, - title: options.title, - body: options.body, - scheduledTime: parseTimeToTimestamp(options.time), - status: 'scheduled' - } - - scheduledNotifications.value.push(notification) - - console.log('✅ Reminder scheduled successfully') - - } catch (error) { - const errorMessage = (error as Error).message - lastError.value = errorMessage - console.error('❌ Failed to schedule reminder:', errorMessage) - throw error - } finally { - isScheduling.value = false - } - } - - async function cancelReminder(reminderId: string): Promise { - if (!Capacitor.isNativePlatform()) { - throw new Error('DailyNotification plugin only available on native platforms') - } - - if (!window.DailyNotification) { - throw new Error('DailyNotification plugin not loaded. Please restart the app.') - } - - try { - isScheduling.value = true - lastError.value = null - - await window.DailyNotification.cancelDailyReminder({ reminderId }) - - // Update local state - const index = scheduledNotifications.value.findIndex(n => n.id === reminderId) - if (index !== -1) { - scheduledNotifications.value[index].status = 'cancelled' - } - - console.log('✅ Reminder cancelled successfully') - - } catch (error) { - const errorMessage = (error as Error).message - lastError.value = errorMessage - console.error('❌ Failed to cancel reminder:', errorMessage) - throw error - } finally { - isScheduling.value = false - } - } - - async function checkStatus(): Promise { - if (!Capacitor.isNativePlatform()) { - console.warn('DailyNotification plugin only available on native platforms') - return - } - - if (!window.DailyNotification) { - console.warn('DailyNotification plugin not loaded') - return - } - - try { - const status = await window.DailyNotification.checkStatus() - console.log('📊 Notification Status:', status) - - // Update app store with status - const { useAppStore } = await import('@/stores/app') - const appStore = useAppStore() - appStore.setNotificationStatus(status) - - } catch (error) { - console.error('❌ Failed to check notification status:', error) - } - } - - async function getLastNotification(): Promise { - if (!Capacitor.isNativePlatform()) { - console.warn('DailyNotification plugin only available on native platforms') - return - } - - if (!window.DailyNotification) { - console.warn('DailyNotification plugin not loaded') - return - } - - try { - const lastNotification = await window.DailyNotification.getLastNotification() - console.log('📱 Last Notification:', lastNotification) - - // Add to history - const historyItem: NotificationHistory = { - id: lastNotification.id, - title: lastNotification.title, - body: lastNotification.body, - scheduledTime: lastNotification.scheduledTime, - deliveredAt: lastNotification.deliveredAt, - clicked: false, - dismissed: false - } - - notificationHistory.value.unshift(historyItem) - - // Keep only last 50 items - if (notificationHistory.value.length > 50) { - notificationHistory.value = notificationHistory.value.slice(0, 50) - } - - } catch (error) { - console.error('❌ Failed to get last notification:', error) - } - } - - function clearError(): void { - lastError.value = null - } - - function clearHistory(): void { - notificationHistory.value = [] - } - - // Helper function to parse time string to timestamp - function parseTimeToTimestamp(timeString: string): number { - const [hours, minutes] = timeString.split(':').map(Number) - const now = new Date() - const scheduled = new Date() - scheduled.setHours(hours, minutes, 0, 0) - - // If time has passed today, schedule for tomorrow - if (scheduled <= now) { - scheduled.setDate(scheduled.getDate() + 1) - } - - return scheduled.getTime() - } - - // Reset store - function $reset(): void { - scheduledNotifications.value = [] - notificationHistory.value = [] - isScheduling.value = false - lastError.value = null - } - - return { - // State - scheduledNotifications, - notificationHistory, - isScheduling, - lastError, - - // Getters - hasScheduledNotifications, - nextNotification, - notificationCount, - - // Actions - scheduleNotification, - scheduleReminder, - cancelReminder, - checkStatus, - getLastNotification, - clearError, - clearHistory, - $reset - } -}) diff --git a/test-apps/android-test/src/views/HistoryView.vue b/test-apps/android-test/src/views/HistoryView.vue deleted file mode 100644 index a322ecc..0000000 --- a/test-apps/android-test/src/views/HistoryView.vue +++ /dev/null @@ -1,144 +0,0 @@ - - - - - - - diff --git a/test-apps/android-test/src/views/HomeView.vue b/test-apps/android-test/src/views/HomeView.vue deleted file mode 100644 index aeb8e61..0000000 --- a/test-apps/android-test/src/views/HomeView.vue +++ /dev/null @@ -1,260 +0,0 @@ - - - - - - - diff --git a/test-apps/android-test/src/views/LogsView.vue b/test-apps/android-test/src/views/LogsView.vue deleted file mode 100644 index e2c97db..0000000 --- a/test-apps/android-test/src/views/LogsView.vue +++ /dev/null @@ -1,629 +0,0 @@ - - - - - - - diff --git a/test-apps/android-test/src/views/NotFoundView.vue b/test-apps/android-test/src/views/NotFoundView.vue deleted file mode 100644 index 91f4b28..0000000 --- a/test-apps/android-test/src/views/NotFoundView.vue +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - diff --git a/test-apps/android-test/src/views/NotificationsView.vue b/test-apps/android-test/src/views/NotificationsView.vue deleted file mode 100644 index e69db72..0000000 --- a/test-apps/android-test/src/views/NotificationsView.vue +++ /dev/null @@ -1,179 +0,0 @@ - - - - - - - diff --git a/test-apps/android-test/src/views/ScheduleView.vue b/test-apps/android-test/src/views/ScheduleView.vue deleted file mode 100644 index 822b82a..0000000 --- a/test-apps/android-test/src/views/ScheduleView.vue +++ /dev/null @@ -1,518 +0,0 @@ - - - - - - - diff --git a/test-apps/android-test/src/views/StatusView.vue b/test-apps/android-test/src/views/StatusView.vue deleted file mode 100644 index 6033dce..0000000 --- a/test-apps/android-test/src/views/StatusView.vue +++ /dev/null @@ -1,310 +0,0 @@ - - - - - - - diff --git a/test-apps/android-test/tsconfig.json b/test-apps/android-test/tsconfig.json deleted file mode 100644 index d8c617b..0000000 --- a/test-apps/android-test/tsconfig.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "useDefineForClassFields": true, - "module": "ESNext", - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "skipLibCheck": true, - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "preserve", - "strict": true, - "noUnusedLocals": false, - "noUnusedParameters": false, - "noFallthroughCasesInSwitch": true, - "experimentalDecorators": true, - "emitDecoratorMetadata": true, - "baseUrl": ".", - "paths": { - "@/*": ["./src/*"], - "@components/*": ["./src/components/*"], - "@views/*": ["./src/views/*"], - "@stores/*": ["./src/stores/*"], - "@services/*": ["./src/services/*"], - "@types/*": ["./src/types/*"], - "@utils/*": ["./src/utils/*"] - }, - "types": [ - "vite/client", - "node" - ] - }, - "include": [ - "env.d.ts", - "src/**/*", - "src/**/*.vue" - ], - "exclude": [ - "src/**/__tests__/*", - "node_modules", - "dist" - ] -} \ No newline at end of file diff --git a/test-apps/android-test/vite.config.ts b/test-apps/android-test/vite.config.ts deleted file mode 100644 index ea79110..0000000 --- a/test-apps/android-test/vite.config.ts +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Vite Configuration for Daily Notification Test App - * - * Vue 3 + TypeScript + Capacitor setup with vue-facing-decorator support - * - * @author Matthew Raymer - * @version 1.0.0 - */ - -import { defineConfig } from 'vite' -import vue from '@vitejs/plugin-vue' -import { resolve } from 'path' - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [vue()], - - // Build configuration for Capacitor - build: { - outDir: 'dist', - assetsDir: 'assets', - sourcemap: true, - rollupOptions: { - input: { - main: resolve(__dirname, 'index.html') - } - } - }, - - // Development server configuration - server: { - host: '0.0.0.0', - port: 3000, - strictPort: true, - hmr: { - port: 3001 - } - }, - - // Preview server configuration - preview: { - host: '0.0.0.0', - port: 4173, - strictPort: true - }, - - // Path resolution - resolve: { - alias: { - '@': resolve(__dirname, 'src'), - '@components': resolve(__dirname, 'src/components'), - '@views': resolve(__dirname, 'src/views'), - '@stores': resolve(__dirname, 'src/stores'), - '@services': resolve(__dirname, 'src/services'), - '@types': resolve(__dirname, 'src/types'), - '@utils': resolve(__dirname, 'src/utils') - } - }, - - // TypeScript configuration - esbuild: { - target: 'es2020' - }, - - // Define global constants - define: { - __VUE_OPTIONS_API__: true, - __VUE_PROD_DEVTOOLS__: false - } -}) diff --git a/test-apps/android-test/webpack.config.js b/test-apps/android-test/webpack.config.js deleted file mode 100644 index 2edfeef..0000000 --- a/test-apps/android-test/webpack.config.js +++ /dev/null @@ -1,33 +0,0 @@ -const path = require('path'); -const HtmlWebpackPlugin = require('html-webpack-plugin'); - -module.exports = { - entry: './src/index.ts', - module: { - rules: [ - { - test: /\.ts$/, - use: 'ts-loader', - exclude: /node_modules/, - }, - ], - }, - resolve: { - extensions: ['.ts', '.js'], - }, - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist'), - clean: true, - }, - plugins: [ - new HtmlWebpackPlugin({ - template: './src/index.html', - }), - ], - devServer: { - static: './dist', - port: 3000, - hot: true, - }, -}; diff --git a/test-apps/check-environment.sh b/test-apps/check-environment.sh deleted file mode 100755 index 365e08f..0000000 --- a/test-apps/check-environment.sh +++ /dev/null @@ -1,112 +0,0 @@ -#!/bin/bash - -# Environment Verification Script for Test Apps -echo "🔍 Verifying Test Apps Environment..." -echo "" - -# Check Node.js -echo "📦 Node.js:" -if command -v node &> /dev/null; then - node_version=$(node --version) - echo " ✅ Installed: $node_version" - - # Check if version is 18+ - major_version=$(echo $node_version | cut -d'.' -f1 | sed 's/v//') - if [ "$major_version" -ge 18 ]; then - echo " ✅ Version 18+ (compatible)" - else - echo " ⚠️ Version $major_version (requires 18+)" - fi -else - echo " ❌ Not installed" -fi - -# Check npm -echo "" -echo "📦 npm:" -if command -v npm &> /dev/null; then - npm_version=$(npm --version) - echo " ✅ Installed: $npm_version" -else - echo " ❌ Not installed" -fi - -# Check Capacitor CLI -echo "" -echo "⚡ Capacitor CLI:" -if command -v cap &> /dev/null; then - cap_version=$(cap --version) - echo " ✅ Installed: $cap_version" -else - echo " ❌ Not installed (will be installed by setup scripts)" -fi - -# Check Android (if available) -echo "" -echo "📱 Android:" -if command -v studio &> /dev/null; then - echo " ✅ Android Studio installed" -else - echo " ❌ Android Studio not found" -fi - -if [ ! -z "$ANDROID_HOME" ]; then - echo " ✅ ANDROID_HOME set: $ANDROID_HOME" -else - echo " ❌ ANDROID_HOME not set" -fi - -if command -v java &> /dev/null; then - java_version=$(java -version 2>&1 | head -n 1) - echo " ✅ Java: $java_version" -else - echo " ❌ Java not found" -fi - -# Check iOS (if on macOS) -echo "" -echo "🍎 iOS:" -if [[ "$OSTYPE" == "darwin"* ]]; then - if command -v xcodebuild &> /dev/null; then - xcode_version=$(xcodebuild -version | head -n 1) - echo " ✅ Xcode: $xcode_version" - else - echo " ❌ Xcode not installed" - fi - - if command -v xcrun &> /dev/null; then - echo " ✅ Xcode Command Line Tools available" - else - echo " ❌ Xcode Command Line Tools not installed" - fi -else - echo " ⚠️ iOS development requires macOS" -fi - -# Check Electron -echo "" -echo "⚡ Electron:" -if command -v npx &> /dev/null; then - electron_version=$(npx electron --version 2>/dev/null) - if [ $? -eq 0 ]; then - echo " ✅ Electron available: $electron_version" - else - echo " ⚠️ Electron not installed (will be installed by setup)" - fi -else - echo " ❌ npx not available" -fi - -echo "" -echo "📋 Summary:" -echo " - Node.js 18+: $(command -v node &> /dev/null && node --version | cut -d'.' -f1 | sed 's/v//' | awk '{if($1>=18) print "✅"; else print "❌"}' || echo "❌")" -echo " - npm: $(command -v npm &> /dev/null && echo "✅" || echo "❌")" -echo " - Android Studio: $(command -v studio &> /dev/null && echo "✅" || echo "❌")" -echo " - Xcode: $(command -v xcodebuild &> /dev/null && echo "✅" || echo "❌")" -echo " - Electron: $(command -v npx &> /dev/null && npx electron --version &> /dev/null && echo "✅" || echo "❌")" - -echo "" -echo "🚀 Next Steps:" -echo " 1. Install missing prerequisites" -echo " 2. Run setup scripts: ./setup-*.sh" -echo " 3. See SETUP_GUIDE.md for detailed instructions" diff --git a/test-apps/config/timesafari-config.json b/test-apps/config/timesafari-config.json deleted file mode 100644 index 9303e1a..0000000 --- a/test-apps/config/timesafari-config.json +++ /dev/null @@ -1,152 +0,0 @@ -{ - "timesafari": { - "appId": "app.timesafari.test", - "appName": "TimeSafari Test", - "version": "1.0.0", - "description": "Test app for TimeSafari Daily Notification Plugin integration" - }, - "endorser": { - "baseUrl": "http://localhost:3001", - "apiVersion": "v2", - "endpoints": { - "offers": "/api/v2/report/offers", - "offersToPlans": "/api/v2/report/offersToPlansOwnedByMe", - "plansLastUpdated": "/api/v2/report/plansLastUpdatedBetween", - "notificationsBundle": "/api/v2/report/notifications/bundle" - }, - "authentication": { - "type": "Bearer", - "token": "test-jwt-token-12345", - "headers": { - "Authorization": "Bearer test-jwt-token-12345", - "Content-Type": "application/json", - "X-Privacy-Level": "user-controlled" - } - }, - "pagination": { - "defaultLimit": 50, - "maxLimit": 100, - "hitLimitThreshold": 50 - } - }, - "notificationTypes": { - "offers": { - "enabled": true, - "types": [ - "new_to_me", - "changed_to_me", - "new_to_projects", - "changed_to_projects", - "new_to_favorites", - "changed_to_favorites" - ] - }, - "projects": { - "enabled": true, - "types": [ - "local_new", - "local_changed", - "content_interest_new", - "favorited_changed" - ] - }, - "people": { - "enabled": true, - "types": [ - "local_new", - "local_changed", - "content_interest_new", - "favorited_changed", - "contacts_changed" - ] - }, - "items": { - "enabled": true, - "types": [ - "local_new", - "local_changed", - "favorited_changed" - ] - } - }, - "scheduling": { - "contentFetch": { - "schedule": "0 8 * * *", - "time": "08:00", - "description": "8 AM daily - fetch community updates" - }, - "userNotification": { - "schedule": "0 9 * * *", - "time": "09:00", - "description": "9 AM daily - notify users of community updates" - } - }, - "testData": { - "userDid": "did:example:testuser123", - "starredPlanIds": [ - "plan-community-garden", - "plan-local-food", - "plan-sustainability" - ], - "lastKnownOfferId": "01HSE3R9MAC0FT3P3KZ382TWV7", - "lastKnownPlanId": "01HSE3R9MAC0FT3P3KZ382TWV8", - "mockOffers": [ - { - "jwtId": "01HSE3R9MAC0FT3P3KZ382TWV7", - "handleId": "offer-web-dev-001", - "offeredByDid": "did:example:offerer123", - "recipientDid": "did:example:testuser123", - "objectDescription": "Web development services for community project", - "unit": "USD", - "amount": 1000, - "amountGiven": 500, - "amountGivenConfirmed": 250 - } - ], - "mockProjects": [ - { - "plan": { - "jwtId": "01HSE3R9MAC0FT3P3KZ382TWV8", - "handleId": "plan-community-garden", - "name": "Community Garden Project", - "description": "Building a community garden for local food production", - "issuerDid": "did:example:issuer123", - "agentDid": "did:example:agent123" - }, - "wrappedClaimBefore": null - } - ] - }, - "callbacks": { - "offers": { - "enabled": true, - "localHandler": "handleOffersNotification" - }, - "projects": { - "enabled": true, - "localHandler": "handleProjectsNotification" - }, - "people": { - "enabled": true, - "localHandler": "handlePeopleNotification" - }, - "items": { - "enabled": true, - "localHandler": "handleItemsNotification" - }, - "communityAnalytics": { - "enabled": true, - "endpoint": "http://localhost:3001/api/analytics/community-events", - "headers": { - "Content-Type": "application/json", - "X-Privacy-Level": "aggregated" - } - } - }, - "observability": { - "enableLogging": true, - "logLevel": "debug", - "enableMetrics": true, - "enableHealthChecks": true - } -} diff --git a/test-apps/daily-notification-test/.editorconfig b/test-apps/daily-notification-test/.editorconfig new file mode 100644 index 0000000..3b510aa --- /dev/null +++ b/test-apps/daily-notification-test/.editorconfig @@ -0,0 +1,8 @@ +[*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,vue,css,scss,sass,less,styl}] +charset = utf-8 +indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true +end_of_line = lf +max_line_length = 100 diff --git a/test-apps/daily-notification-test/.gitattributes b/test-apps/daily-notification-test/.gitattributes new file mode 100644 index 0000000..6313b56 --- /dev/null +++ b/test-apps/daily-notification-test/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf diff --git a/test-apps/daily-notification-test/.gitignore b/test-apps/daily-notification-test/.gitignore new file mode 100644 index 0000000..8ee54e8 --- /dev/null +++ b/test-apps/daily-notification-test/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/test-apps/daily-notification-test/README.md b/test-apps/daily-notification-test/README.md new file mode 100644 index 0000000..9c44d3a --- /dev/null +++ b/test-apps/daily-notification-test/README.md @@ -0,0 +1,48 @@ +# daily-notification-test + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VS Code](https://code.visualstudio.com/) + [Vue (Official)](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur). + +## Recommended Browser Setup + +- Chromium-based browsers (Chrome, Edge, Brave, etc.): + - [Vue.js devtools](https://chromewebstore.google.com/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd) + - [Turn on Custom Object Formatter in Chrome DevTools](http://bit.ly/object-formatters) +- Firefox: + - [Vue.js devtools](https://addons.mozilla.org/en-US/firefox/addon/vue-js-devtools/) + - [Turn on Custom Object Formatter in Firefox DevTools](https://fxdx.dev/firefox-devtools-custom-object-formatters/) + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types. + +## Customize configuration + +See [Vite Configuration Reference](https://vite.dev/config/). + +## Project Setup + +```sh +npm install +``` + +### Compile and Hot-Reload for Development + +```sh +npm run dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +npm run build +``` + +### Lint with [ESLint](https://eslint.org/) + +```sh +npm run lint +``` diff --git a/test-apps/daily-notification-test/android/.gitignore b/test-apps/daily-notification-test/android/.gitignore new file mode 100644 index 0000000..48354a3 --- /dev/null +++ b/test-apps/daily-notification-test/android/.gitignore @@ -0,0 +1,101 @@ +# Using Android gitignore template: https://github.com/github/gitignore/blob/HEAD/Android.gitignore + +# Built application files +*.apk +*.aar +*.ap_ +*.aab + +# Files for the ART/Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ +out/ +# Uncomment the following line in case you need and you don't have the release build type files in your app +# release/ + +# Gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +*.log + +# Android Studio Navigation editor temp files +.navigation/ + +# Android Studio captures folder +captures/ + +# IntelliJ +*.iml +.idea/workspace.xml +.idea/tasks.xml +.idea/gradle.xml +.idea/assetWizardSettings.xml +.idea/dictionaries +.idea/libraries +# Android Studio 3 in .gitignore file. +.idea/caches +.idea/modules.xml +# Comment next line if keeping position of elements in Navigation Editor is relevant for you +.idea/navEditor.xml + +# Keystore files +# Uncomment the following lines if you do not want to check your keystore files in. +#*.jks +#*.keystore + +# External native build folder generated in Android Studio 2.2 and later +.externalNativeBuild +.cxx/ + +# Google Services (e.g. APIs or Firebase) +# google-services.json + +# Freeline +freeline.py +freeline/ +freeline_project_description.json + +# fastlane +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots +fastlane/test_output +fastlane/readme.md + +# Version control +vcs.xml + +# lint +lint/intermediates/ +lint/generated/ +lint/outputs/ +lint/tmp/ +# lint/reports/ + +# Android Profiling +*.hprof + +# Cordova plugins for Capacitor +capacitor-cordova-android-plugins + +# Copied web assets +app/src/main/assets/public + +# Generated Config files +app/src/main/assets/capacitor.config.json +app/src/main/assets/capacitor.plugins.json +app/src/main/res/xml/config.xml diff --git a/test-apps/daily-notification-test/android/app/.gitignore b/test-apps/daily-notification-test/android/app/.gitignore new file mode 100644 index 0000000..043df80 --- /dev/null +++ b/test-apps/daily-notification-test/android/app/.gitignore @@ -0,0 +1,2 @@ +/build/* +!/build/.npmkeep diff --git a/test-apps/daily-notification-test/android/app/build.gradle b/test-apps/daily-notification-test/android/app/build.gradle new file mode 100644 index 0000000..14c6924 --- /dev/null +++ b/test-apps/daily-notification-test/android/app/build.gradle @@ -0,0 +1,54 @@ +apply plugin: 'com.android.application' + +android { + namespace "com.timesafari.dailynotification.test" + compileSdkVersion rootProject.ext.compileSdkVersion + defaultConfig { + applicationId "com.timesafari.dailynotification.test" + minSdkVersion rootProject.ext.minSdkVersion + targetSdkVersion rootProject.ext.targetSdkVersion + versionCode 1 + versionName "1.0" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + aaptOptions { + // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. + // Default: https://android.googlesource.com/platform/frameworks/base/+/282e181b58cf72b6ca770dc7ca5f91f135444502/tools/aapt/AaptAssets.cpp#61 + ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~' + } + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +repositories { + flatDir{ + dirs '../capacitor-cordova-android-plugins/src/main/libs', 'libs' + } +} + +dependencies { + implementation fileTree(include: ['*.jar'], dir: 'libs') + implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion" + implementation "androidx.coordinatorlayout:coordinatorlayout:$androidxCoordinatorLayoutVersion" + implementation "androidx.core:core-splashscreen:$coreSplashScreenVersion" + implementation project(':capacitor-android') + testImplementation "junit:junit:$junitVersion" + androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion" + androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion" + implementation project(':capacitor-cordova-android-plugins') +} + +apply from: 'capacitor.build.gradle' + +try { + def servicesJSON = file('google-services.json') + if (servicesJSON.text) { + apply plugin: 'com.google.gms.google-services' + } +} catch(Exception e) { + logger.info("google-services.json not found, google-services plugin not applied. Push Notifications won't work") +} diff --git a/test-apps/daily-notification-test/android/app/capacitor.build.gradle b/test-apps/daily-notification-test/android/app/capacitor.build.gradle new file mode 100644 index 0000000..fdb4970 --- /dev/null +++ b/test-apps/daily-notification-test/android/app/capacitor.build.gradle @@ -0,0 +1,19 @@ +// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN + +android { + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } +} + +apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle" +dependencies { + + +} + + +if (hasProperty('postBuildExtras')) { + postBuildExtras() +} diff --git a/test-apps/daily-notification-test/android/app/proguard-rules.pro b/test-apps/daily-notification-test/android/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/test-apps/daily-notification-test/android/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/test-apps/daily-notification-test/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java b/test-apps/daily-notification-test/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java new file mode 100644 index 0000000..f2c2217 --- /dev/null +++ b/test-apps/daily-notification-test/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.getcapacitor.myapp; + +import static org.junit.Assert.*; + +import android.content.Context; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.platform.app.InstrumentationRegistry; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + + @Test + public void useAppContext() throws Exception { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + + assertEquals("com.getcapacitor.app", appContext.getPackageName()); + } +} diff --git a/test-apps/daily-notification-test/android/app/src/main/AndroidManifest.xml b/test-apps/daily-notification-test/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..5c411e0 --- /dev/null +++ b/test-apps/daily-notification-test/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test-apps/daily-notification-test/android/app/src/main/java/com/timesafari/dailynotification/test/MainActivity.java b/test-apps/daily-notification-test/android/app/src/main/java/com/timesafari/dailynotification/test/MainActivity.java new file mode 100644 index 0000000..d9ffcc7 --- /dev/null +++ b/test-apps/daily-notification-test/android/app/src/main/java/com/timesafari/dailynotification/test/MainActivity.java @@ -0,0 +1,5 @@ +package com.timesafari.dailynotification.test; + +import com.getcapacitor.BridgeActivity; + +public class MainActivity extends BridgeActivity {} diff --git a/test-apps/daily-notification-test/android/app/src/main/res/drawable-land-hdpi/splash.png b/test-apps/daily-notification-test/android/app/src/main/res/drawable-land-hdpi/splash.png new file mode 100644 index 0000000..e31573b Binary files /dev/null and b/test-apps/daily-notification-test/android/app/src/main/res/drawable-land-hdpi/splash.png differ diff --git a/test-apps/daily-notification-test/android/app/src/main/res/drawable-land-mdpi/splash.png b/test-apps/daily-notification-test/android/app/src/main/res/drawable-land-mdpi/splash.png new file mode 100644 index 0000000..f7a6492 Binary files /dev/null and b/test-apps/daily-notification-test/android/app/src/main/res/drawable-land-mdpi/splash.png differ diff --git a/test-apps/daily-notification-test/android/app/src/main/res/drawable-land-xhdpi/splash.png b/test-apps/daily-notification-test/android/app/src/main/res/drawable-land-xhdpi/splash.png new file mode 100644 index 0000000..8077255 Binary files /dev/null and b/test-apps/daily-notification-test/android/app/src/main/res/drawable-land-xhdpi/splash.png differ diff --git a/test-apps/daily-notification-test/android/app/src/main/res/drawable-land-xxhdpi/splash.png b/test-apps/daily-notification-test/android/app/src/main/res/drawable-land-xxhdpi/splash.png new file mode 100644 index 0000000..14c6c8f Binary files /dev/null and b/test-apps/daily-notification-test/android/app/src/main/res/drawable-land-xxhdpi/splash.png differ diff --git a/test-apps/daily-notification-test/android/app/src/main/res/drawable-land-xxxhdpi/splash.png b/test-apps/daily-notification-test/android/app/src/main/res/drawable-land-xxxhdpi/splash.png new file mode 100644 index 0000000..244ca25 Binary files /dev/null and b/test-apps/daily-notification-test/android/app/src/main/res/drawable-land-xxxhdpi/splash.png differ diff --git a/test-apps/daily-notification-test/android/app/src/main/res/drawable-port-hdpi/splash.png b/test-apps/daily-notification-test/android/app/src/main/res/drawable-port-hdpi/splash.png new file mode 100644 index 0000000..74faaa5 Binary files /dev/null and b/test-apps/daily-notification-test/android/app/src/main/res/drawable-port-hdpi/splash.png differ diff --git a/test-apps/daily-notification-test/android/app/src/main/res/drawable-port-mdpi/splash.png b/test-apps/daily-notification-test/android/app/src/main/res/drawable-port-mdpi/splash.png new file mode 100644 index 0000000..e944f4a Binary files /dev/null and b/test-apps/daily-notification-test/android/app/src/main/res/drawable-port-mdpi/splash.png differ diff --git a/test-apps/daily-notification-test/android/app/src/main/res/drawable-port-xhdpi/splash.png b/test-apps/daily-notification-test/android/app/src/main/res/drawable-port-xhdpi/splash.png new file mode 100644 index 0000000..564a82f Binary files /dev/null and b/test-apps/daily-notification-test/android/app/src/main/res/drawable-port-xhdpi/splash.png differ diff --git a/test-apps/daily-notification-test/android/app/src/main/res/drawable-port-xxhdpi/splash.png b/test-apps/daily-notification-test/android/app/src/main/res/drawable-port-xxhdpi/splash.png new file mode 100644 index 0000000..bfabe68 Binary files /dev/null and b/test-apps/daily-notification-test/android/app/src/main/res/drawable-port-xxhdpi/splash.png differ diff --git a/test-apps/daily-notification-test/android/app/src/main/res/drawable-port-xxxhdpi/splash.png b/test-apps/daily-notification-test/android/app/src/main/res/drawable-port-xxxhdpi/splash.png new file mode 100644 index 0000000..6929071 Binary files /dev/null and b/test-apps/daily-notification-test/android/app/src/main/res/drawable-port-xxxhdpi/splash.png differ diff --git a/test-apps/daily-notification-test/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/test-apps/daily-notification-test/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..c7bd21d --- /dev/null +++ b/test-apps/daily-notification-test/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/test-apps/daily-notification-test/android/app/src/main/res/drawable/ic_launcher_background.xml b/test-apps/daily-notification-test/android/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..d5fccc5 --- /dev/null +++ b/test-apps/daily-notification-test/android/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test-apps/daily-notification-test/android/app/src/main/res/drawable/splash.png b/test-apps/daily-notification-test/android/app/src/main/res/drawable/splash.png new file mode 100644 index 0000000..f7a6492 Binary files /dev/null and b/test-apps/daily-notification-test/android/app/src/main/res/drawable/splash.png differ diff --git a/test-apps/daily-notification-test/android/app/src/main/res/layout/activity_main.xml b/test-apps/daily-notification-test/android/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..b5ad138 --- /dev/null +++ b/test-apps/daily-notification-test/android/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/test-apps/daily-notification-test/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..036d09b --- /dev/null +++ b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/test-apps/daily-notification-test/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..036d09b --- /dev/null +++ b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/test-apps/daily-notification-test/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..c023e50 Binary files /dev/null and b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/test-apps/daily-notification-test/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..2127973 Binary files /dev/null and b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ diff --git a/test-apps/daily-notification-test/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..b441f37 Binary files /dev/null and b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/test-apps/daily-notification-test/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..72905b8 Binary files /dev/null and b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/test-apps/daily-notification-test/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..8ed0605 Binary files /dev/null and b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ diff --git a/test-apps/daily-notification-test/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..9502e47 Binary files /dev/null and b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/test-apps/daily-notification-test/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..4d1e077 Binary files /dev/null and b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/test-apps/daily-notification-test/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..df0f158 Binary files /dev/null and b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ diff --git a/test-apps/daily-notification-test/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..853db04 Binary files /dev/null and b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/test-apps/daily-notification-test/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..6cdf97c Binary files /dev/null and b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/test-apps/daily-notification-test/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..2960cbb Binary files /dev/null and b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ diff --git a/test-apps/daily-notification-test/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..8e3093a Binary files /dev/null and b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/test-apps/daily-notification-test/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..46de6e2 Binary files /dev/null and b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/test-apps/daily-notification-test/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..d2ea9ab Binary files /dev/null and b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ diff --git a/test-apps/daily-notification-test/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..a40d73e Binary files /dev/null and b/test-apps/daily-notification-test/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/test-apps/daily-notification-test/android/app/src/main/res/values/ic_launcher_background.xml b/test-apps/daily-notification-test/android/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 0000000..c5d5899 --- /dev/null +++ b/test-apps/daily-notification-test/android/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #FFFFFF + \ No newline at end of file diff --git a/test-apps/daily-notification-test/android/app/src/main/res/values/strings.xml b/test-apps/daily-notification-test/android/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..edab104 --- /dev/null +++ b/test-apps/daily-notification-test/android/app/src/main/res/values/strings.xml @@ -0,0 +1,7 @@ + + + Daily Notification Test + Daily Notification Test + com.timesafari.dailynotification.test + com.timesafari.dailynotification.test + diff --git a/test-apps/daily-notification-test/android/app/src/main/res/values/styles.xml b/test-apps/daily-notification-test/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..be874e5 --- /dev/null +++ b/test-apps/daily-notification-test/android/app/src/main/res/values/styles.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/test-apps/daily-notification-test/android/app/src/main/res/xml/file_paths.xml b/test-apps/daily-notification-test/android/app/src/main/res/xml/file_paths.xml new file mode 100644 index 0000000..bd0c4d8 --- /dev/null +++ b/test-apps/daily-notification-test/android/app/src/main/res/xml/file_paths.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/test-apps/daily-notification-test/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java b/test-apps/daily-notification-test/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java new file mode 100644 index 0000000..0297327 --- /dev/null +++ b/test-apps/daily-notification-test/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java @@ -0,0 +1,18 @@ +package com.getcapacitor.myapp; + +import static org.junit.Assert.*; + +import org.junit.Test; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + + @Test + public void addition_isCorrect() throws Exception { + assertEquals(4, 2 + 2); + } +} diff --git a/test-apps/daily-notification-test/android/build.gradle b/test-apps/daily-notification-test/android/build.gradle new file mode 100644 index 0000000..f1b3b0e --- /dev/null +++ b/test-apps/daily-notification-test/android/build.gradle @@ -0,0 +1,29 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + + repositories { + google() + mavenCentral() + } + dependencies { + classpath 'com.android.tools.build:gradle:8.7.2' + classpath 'com.google.gms:google-services:4.4.2' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +apply from: "variables.gradle" + +allprojects { + repositories { + google() + mavenCentral() + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/test-apps/daily-notification-test/android/capacitor.settings.gradle b/test-apps/daily-notification-test/android/capacitor.settings.gradle new file mode 100644 index 0000000..9a5fa87 --- /dev/null +++ b/test-apps/daily-notification-test/android/capacitor.settings.gradle @@ -0,0 +1,3 @@ +// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN +include ':capacitor-android' +project(':capacitor-android').projectDir = new File('../node_modules/@capacitor/android/capacitor') diff --git a/test-apps/daily-notification-test/android/gradle.properties b/test-apps/daily-notification-test/android/gradle.properties new file mode 100644 index 0000000..2e87c52 --- /dev/null +++ b/test-apps/daily-notification-test/android/gradle.properties @@ -0,0 +1,22 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx1536m + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true + +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true diff --git a/test-apps/daily-notification-test/android/gradle/wrapper/gradle-wrapper.jar b/test-apps/daily-notification-test/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..a4b76b9 Binary files /dev/null and b/test-apps/daily-notification-test/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/test-apps/daily-notification-test/android/gradle/wrapper/gradle-wrapper.properties b/test-apps/daily-notification-test/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..c1d5e01 --- /dev/null +++ b/test-apps/daily-notification-test/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/test-apps/daily-notification-test/android/gradlew b/test-apps/daily-notification-test/android/gradlew new file mode 100755 index 0000000..f5feea6 --- /dev/null +++ b/test-apps/daily-notification-test/android/gradlew @@ -0,0 +1,252 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/test-apps/daily-notification-test/android/gradlew.bat b/test-apps/daily-notification-test/android/gradlew.bat new file mode 100644 index 0000000..9d21a21 --- /dev/null +++ b/test-apps/daily-notification-test/android/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/test-apps/daily-notification-test/android/settings.gradle b/test-apps/daily-notification-test/android/settings.gradle new file mode 100644 index 0000000..3b4431d --- /dev/null +++ b/test-apps/daily-notification-test/android/settings.gradle @@ -0,0 +1,5 @@ +include ':app' +include ':capacitor-cordova-android-plugins' +project(':capacitor-cordova-android-plugins').projectDir = new File('./capacitor-cordova-android-plugins/') + +apply from: 'capacitor.settings.gradle' \ No newline at end of file diff --git a/test-apps/daily-notification-test/android/variables.gradle b/test-apps/daily-notification-test/android/variables.gradle new file mode 100644 index 0000000..2c8e408 --- /dev/null +++ b/test-apps/daily-notification-test/android/variables.gradle @@ -0,0 +1,16 @@ +ext { + minSdkVersion = 23 + compileSdkVersion = 35 + targetSdkVersion = 35 + androidxActivityVersion = '1.9.2' + androidxAppCompatVersion = '1.7.0' + androidxCoordinatorLayoutVersion = '1.2.0' + androidxCoreVersion = '1.15.0' + androidxFragmentVersion = '1.8.4' + coreSplashScreenVersion = '1.0.1' + androidxWebkitVersion = '1.12.1' + junitVersion = '4.13.2' + androidxJunitVersion = '1.2.1' + androidxEspressoCoreVersion = '3.6.1' + cordovaAndroidVersion = '10.1.1' +} \ No newline at end of file diff --git a/test-apps/daily-notification-test/capacitor.config.ts b/test-apps/daily-notification-test/capacitor.config.ts new file mode 100644 index 0000000..4ba1229 --- /dev/null +++ b/test-apps/daily-notification-test/capacitor.config.ts @@ -0,0 +1,14 @@ +import type { CapacitorConfig } from '@capacitor/cli'; + +const config: CapacitorConfig = { + appId: 'com.timesafari.dailynotification.test', + appName: 'Daily Notification Test', + webDir: 'dist', + plugins: { + Clipboard: { + // Enable clipboard functionality + } + } +}; + +export default config; diff --git a/test-apps/daily-notification-test/env.d.ts b/test-apps/daily-notification-test/env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/test-apps/daily-notification-test/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/test-apps/daily-notification-test/eslint.config.ts b/test-apps/daily-notification-test/eslint.config.ts new file mode 100644 index 0000000..edb1bbb --- /dev/null +++ b/test-apps/daily-notification-test/eslint.config.ts @@ -0,0 +1,20 @@ +import { globalIgnores } from 'eslint/config' +import { defineConfigWithVueTs, vueTsConfigs } from '@vue/eslint-config-typescript' +import pluginVue from 'eslint-plugin-vue' + +// To allow more languages other than `ts` in `.vue` files, uncomment the following lines: +// import { configureVueProject } from '@vue/eslint-config-typescript' +// configureVueProject({ scriptLangs: ['ts', 'tsx'] }) +// More info at https://github.com/vuejs/eslint-config-typescript/#advanced-setup + +export default defineConfigWithVueTs( + { + name: 'app/files-to-lint', + files: ['**/*.{ts,mts,tsx,vue}'], + }, + + globalIgnores(['**/dist/**', '**/dist-ssr/**', '**/coverage/**']), + + pluginVue.configs['flat/essential'], + vueTsConfigs.recommended, +) diff --git a/test-apps/daily-notification-test/index.html b/test-apps/daily-notification-test/index.html new file mode 100644 index 0000000..9e5fc8f --- /dev/null +++ b/test-apps/daily-notification-test/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/test-apps/android-test/package-lock.json b/test-apps/daily-notification-test/package-lock.json similarity index 56% rename from test-apps/android-test/package-lock.json rename to test-apps/daily-notification-test/package-lock.json index dfa1eac..18080d8 100644 --- a/test-apps/android-test/package-lock.json +++ b/test-apps/daily-notification-test/package-lock.json @@ -1,35 +1,305 @@ { - "name": "daily-notification-android-test", - "version": "1.0.0", + "name": "daily-notification-test", + "version": "0.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "daily-notification-android-test", - "version": "1.0.0", + "name": "daily-notification-test", + "version": "0.0.0", + "dependencies": { + "@capacitor/android": "^6.2.1", + "@capacitor/cli": "^6.2.1", + "@capacitor/core": "^6.2.1", + "date-fns": "^4.1.0", + "pinia": "^3.0.3", + "vue": "^3.5.22", + "vue-facing-decorator": "^4.0.1", + "vue-router": "^4.5.1" + }, + "devDependencies": { + "@tsconfig/node22": "^22.0.2", + "@types/node": "^22.18.6", + "@vitejs/plugin-vue": "^6.0.1", + "@vue/eslint-config-typescript": "^14.6.0", + "@vue/tsconfig": "^0.8.1", + "eslint": "^9.33.0", + "eslint-plugin-vue": "~10.4.0", + "jiti": "^2.5.1", + "npm-run-all2": "^8.0.4", + "typescript": "~5.9.0", + "vite": "^7.1.7", + "vite-plugin-vue-devtools": "^8.0.2", + "vue-tsc": "^3.1.0" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dev": true, "license": "MIT", "dependencies": { - "@capacitor/android": "^5.0.0", - "@capacitor/cli": "^5.0.0", - "@capacitor/core": "^5.0.0", - "pinia": "^2.1.0", - "vue": "^3.4.0", - "vue-facing-decorator": "^3.0.0", - "vue-router": "^4.2.0" + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" }, - "devDependencies": { - "@capacitor/cli": "^5.0.0", - "@types/node": "^20.0.0", - "@typescript-eslint/eslint-plugin": "^6.0.0", - "@typescript-eslint/parser": "^6.0.0", - "@vitejs/plugin-vue": "^4.5.0", - "@vue/eslint-config-typescript": "^12.0.0", - "@vue/tsconfig": "^0.5.0", - "eslint": "^8.0.0", - "eslint-plugin-vue": "^9.0.0", - "typescript": "~5.3.0", - "vite": "^5.0.0", - "vue-tsc": "^1.8.0" + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.4.tgz", + "integrity": "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", + "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.4", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.4", + "@babel/types": "^7.28.4", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", + "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.3", + "@babel/types": "^7.28.2", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", + "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.3" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.3.tgz", + "integrity": "sha512-V9f6ZFIYSLNEbuGA/92uOvYsGCJNsuA8ESZ4ldc09bWk/j8H8TKiPw8Mk1eG6olpnO0ALHJmYfZvF4MEE4gajg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/traverse": "^7.28.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz", + "integrity": "sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", + "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz", + "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", + "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { @@ -50,6 +320,30 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/parser": { "version": "7.28.4", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", @@ -65,6 +359,155 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/plugin-proposal-decorators": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.28.0.tgz", + "integrity": "sha512-zOiZqvANjWDUaUS9xMxbMcK/Zccztbe/6ikvUXaG9nsPH3w6qh5UaPGAnirI/WhIbZ8m3OHU0ReyPrknG+ZKeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-syntax-decorators": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-decorators": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.27.1.tgz", + "integrity": "sha512-YMq8Z87Lhl8EGkmb0MwYkt36QnxC+fzCgrl66ereamPlYToRpIk5nUjKUY3QKLWq8mwUB1BgbeXcTJhZOCDg5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", + "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", + "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", + "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.0.tgz", + "integrity": "sha512-4AEiDEBPIZvLQaWlc9liCavE0xRM0dNca41WtBeM3jgFptfUOSG9z0uteLhq6+3rq+WB6jIvUwKDTpXEHPJ2Vg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz", + "integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.4", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/types": { "version": "7.28.4", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", @@ -79,60 +522,112 @@ } }, "node_modules/@capacitor/android": { - "version": "5.7.8", - "resolved": "https://registry.npmjs.org/@capacitor/android/-/android-5.7.8.tgz", - "integrity": "sha512-ooWclwcuW0dy3YfqgoozkHkjatX8H2fb2/RwRsJa3cew1P1lUXIXri3Dquuy4LdqFAJA7UHcJ19Bl/6UKdsZYA==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@capacitor/android/-/android-6.2.1.tgz", + "integrity": "sha512-8gd4CIiQO5LAIlPIfd5mCuodBRxMMdZZEdj8qG8m+dQ1sQ2xyemVpzHmRK8qSCHorsBUCg3D62j2cp6bEBAkdw==", "license": "MIT", "peerDependencies": { - "@capacitor/core": "^5.7.0" + "@capacitor/core": "^6.2.0" } }, "node_modules/@capacitor/cli": { - "version": "5.7.8", - "resolved": "https://registry.npmjs.org/@capacitor/cli/-/cli-5.7.8.tgz", - "integrity": "sha512-qN8LDlREMhrYhOvVXahoJVNkP8LP55/YPRJrzTAFrMqlNJC18L3CzgWYIblFPnuwfbH/RxbfoZT/ydkwgVpMrw==", - "dev": true, + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@capacitor/cli/-/cli-6.2.1.tgz", + "integrity": "sha512-JKl0FpFge8PgQNInw12kcKieQ4BmOyazQ4JGJOfEpVXlgrX1yPhSZTPjngupzTCiK3I7q7iGG5kjun0fDqgSCA==", + "license": "MIT", + "dependencies": { + "@ionic/cli-framework-output": "^2.2.5", + "@ionic/utils-fs": "^3.1.6", + "@ionic/utils-subprocess": "2.1.11", + "@ionic/utils-terminal": "^2.3.3", + "commander": "^9.3.0", + "debug": "^4.3.4", + "env-paths": "^2.2.0", + "kleur": "^4.1.4", + "native-run": "^2.0.0", + "open": "^8.4.0", + "plist": "^3.0.5", + "prompts": "^2.4.2", + "rimraf": "^4.4.1", + "semver": "^7.3.7", + "tar": "^6.1.11", + "tslib": "^2.4.0", + "xml2js": "^0.5.0" + }, + "bin": { + "cap": "bin/capacitor", + "capacitor": "bin/capacitor" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@capacitor/cli/node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@capacitor/cli/node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@capacitor/cli/node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@capacitor/cli/node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", "license": "MIT", "dependencies": { - "@ionic/cli-framework-output": "^2.2.5", - "@ionic/utils-fs": "^3.1.6", - "@ionic/utils-subprocess": "^2.1.11", - "@ionic/utils-terminal": "^2.3.3", - "commander": "^9.3.0", - "debug": "^4.3.4", - "env-paths": "^2.2.0", - "kleur": "^4.1.4", - "native-run": "^2.0.0", - "open": "^8.4.0", - "plist": "^3.0.5", - "prompts": "^2.4.2", - "rimraf": "^4.4.1", - "semver": "^7.3.7", - "tar": "^6.1.11", - "tslib": "^2.4.0", - "xml2js": "^0.5.0" - }, - "bin": { - "cap": "bin/capacitor", - "capacitor": "bin/capacitor" + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" }, "engines": { - "node": ">=16.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/@capacitor/core": { - "version": "5.7.8", - "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-5.7.8.tgz", - "integrity": "sha512-rrZcm/2vJM0WdWRQup1TUidbjQV9PfIadSkV4rAGLD7R6PuzZSMPGT0gmoZzCRlXkqrazrWWDkurei3ozU02FA==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-6.2.1.tgz", + "integrity": "sha512-urZwxa7hVE/BnA18oCFAdizXPse6fCKanQyEqpmz6cBJ2vObwMpyJDG5jBeoSsgocS9+Ax+9vb4ducWJn0y2qQ==", "license": "MIT", "dependencies": { "tslib": "^2.1.0" } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.11.tgz", + "integrity": "sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg==", "cpu": [ "ppc64" ], @@ -143,13 +638,13 @@ "aix" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.11.tgz", + "integrity": "sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg==", "cpu": [ "arm" ], @@ -160,13 +655,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.11.tgz", + "integrity": "sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ==", "cpu": [ "arm64" ], @@ -177,13 +672,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.11.tgz", + "integrity": "sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g==", "cpu": [ "x64" ], @@ -194,13 +689,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.11.tgz", + "integrity": "sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w==", "cpu": [ "arm64" ], @@ -211,13 +706,13 @@ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.11.tgz", + "integrity": "sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ==", "cpu": [ "x64" ], @@ -228,13 +723,13 @@ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.11.tgz", + "integrity": "sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA==", "cpu": [ "arm64" ], @@ -245,13 +740,13 @@ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.11.tgz", + "integrity": "sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw==", "cpu": [ "x64" ], @@ -262,13 +757,13 @@ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.11.tgz", + "integrity": "sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw==", "cpu": [ "arm" ], @@ -279,13 +774,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.11.tgz", + "integrity": "sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA==", "cpu": [ "arm64" ], @@ -296,13 +791,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.11.tgz", + "integrity": "sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw==", "cpu": [ "ia32" ], @@ -313,13 +808,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.11.tgz", + "integrity": "sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw==", "cpu": [ "loong64" ], @@ -330,13 +825,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.11.tgz", + "integrity": "sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ==", "cpu": [ "mips64el" ], @@ -347,13 +842,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.11.tgz", + "integrity": "sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw==", "cpu": [ "ppc64" ], @@ -364,13 +859,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.11.tgz", + "integrity": "sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww==", "cpu": [ "riscv64" ], @@ -381,13 +876,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.11.tgz", + "integrity": "sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw==", "cpu": [ "s390x" ], @@ -398,13 +893,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.11.tgz", + "integrity": "sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ==", "cpu": [ "x64" ], @@ -415,13 +910,30 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.11.tgz", + "integrity": "sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.11.tgz", + "integrity": "sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A==", "cpu": [ "x64" ], @@ -432,13 +944,30 @@ "netbsd" ], "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.11.tgz", + "integrity": "sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.11.tgz", + "integrity": "sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw==", "cpu": [ "x64" ], @@ -449,13 +978,30 @@ "openbsd" ], "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.11.tgz", + "integrity": "sha512-rOREuNIQgaiR+9QuNkbkxubbp8MSO9rONmwP5nKncnWJ9v5jQ4JxFnLu4zDSRPf3x4u+2VN4pM4RdyIzDty/wQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.11.tgz", + "integrity": "sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA==", "cpu": [ "x64" ], @@ -466,13 +1012,13 @@ "sunos" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.11.tgz", + "integrity": "sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q==", "cpu": [ "arm64" ], @@ -483,13 +1029,13 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.11.tgz", + "integrity": "sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA==", "cpu": [ "ia32" ], @@ -500,13 +1046,13 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.11.tgz", + "integrity": "sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA==", "cpu": [ "x64" ], @@ -517,7 +1063,7 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@eslint-community/eslint-utils": { @@ -549,17 +1095,82 @@ "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, + "node_modules/@eslint/config-array": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.0.tgz", + "integrity": "sha512-WUFvV4WoIwW8Bv0KeKCIIEgdSiFOsulyN0xrMu+7z43q/hkOLXjvb5u7UC9jDxvRzcrbEmuZBX5yJZz1741jog==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.16.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.16.0.tgz", + "integrity": "sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", "dev": true, "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -567,29 +1178,12 @@ "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, - "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", @@ -601,13 +1195,6 @@ "concat-map": "0.0.1" } }, - "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, "node_modules/@eslint/eslintrc/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -622,53 +1209,64 @@ } }, "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==", + "version": "9.37.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.37.0.tgz", + "integrity": "sha512-jaS+NJ+hximswBG6pjNX0uEJZkrT0zwpVi3BA3vX22aFGjJjmgSTSmPpZCRKmoBL5VY/M6p0xsSJx7rk7sy5gg==", "dev": true, "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@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", + "node_modules/@eslint/plugin-kit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.0.tgz", + "integrity": "sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "@eslint/core": "^0.16.0", + "levn": "^0.4.1" }, "engines": { - "node": ">=10.10.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" } }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", "dev": true, - "license": "ISC", + "license": "Apache-2.0", "dependencies": { - "brace-expansion": "^1.1.7" + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" }, "engines": { - "node": "*" + "node": ">=18.18.0" } }, "node_modules/@humanwhocodes/module-importer": { @@ -685,19 +1283,24 @@ "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", + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", "dev": true, - "license": "BSD-3-Clause" + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@ionic/cli-framework-output": { "version": "2.2.8", "resolved": "https://registry.npmjs.org/@ionic/cli-framework-output/-/cli-framework-output-2.2.8.tgz", "integrity": "sha512-TshtaFQsovB4NWRBydbNFawql6yul7d5bMiW1WYYf17hd99V6xdDdk3vtF51bw6sLkxON3bDQpWsnUc9/hVo3g==", - "dev": true, "license": "MIT", "dependencies": { "@ionic/utils-terminal": "2.3.5", @@ -709,24 +1312,22 @@ } }, "node_modules/@ionic/utils-array": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@ionic/utils-array/-/utils-array-2.1.6.tgz", - "integrity": "sha512-0JZ1Zkp3wURnv8oq6Qt7fMPo5MpjbLoUoa9Bu2Q4PJuSDWM8H8gwF3dQO7VTeUj3/0o1IB1wGkFWZZYgUXZMUg==", - "dev": true, + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@ionic/utils-array/-/utils-array-2.1.5.tgz", + "integrity": "sha512-HD72a71IQVBmQckDwmA8RxNVMTbxnaLbgFOl+dO5tbvW9CkkSFCv41h6fUuNsSEVgngfkn0i98HDuZC8mk+lTA==", "license": "MIT", "dependencies": { "debug": "^4.0.0", "tslib": "^2.0.1" }, "engines": { - "node": ">=16.0.0" + "node": ">=10.3.0" } }, "node_modules/@ionic/utils-fs": { "version": "3.1.7", "resolved": "https://registry.npmjs.org/@ionic/utils-fs/-/utils-fs-3.1.7.tgz", "integrity": "sha512-2EknRvMVfhnyhL1VhFkSLa5gOcycK91VnjfrTB0kbqkTFCOXyXgVLI5whzq7SLrgD9t1aqos3lMMQyVzaQ5gVA==", - "dev": true, "license": "MIT", "dependencies": { "@types/fs-extra": "^8.0.0", @@ -739,42 +1340,39 @@ } }, "node_modules/@ionic/utils-object": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@ionic/utils-object/-/utils-object-2.1.6.tgz", - "integrity": "sha512-vCl7sl6JjBHFw99CuAqHljYJpcE88YaH2ZW4ELiC/Zwxl5tiwn4kbdP/gxi2OT3MQb1vOtgAmSNRtusvgxI8ww==", - "dev": true, + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@ionic/utils-object/-/utils-object-2.1.5.tgz", + "integrity": "sha512-XnYNSwfewUqxq+yjER1hxTKggftpNjFLJH0s37jcrNDwbzmbpFTQTVAp4ikNK4rd9DOebX/jbeZb8jfD86IYxw==", "license": "MIT", "dependencies": { "debug": "^4.0.0", "tslib": "^2.0.1" }, "engines": { - "node": ">=16.0.0" + "node": ">=10.3.0" } }, "node_modules/@ionic/utils-process": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/@ionic/utils-process/-/utils-process-2.1.11.tgz", - "integrity": "sha512-Uavxn+x8j3rDlZEk1X7YnaN6wCgbCwYQOeIjv/m94i1dzslqWhqIHEqxEyeE8HsT5Negboagg7GtQiABy+BLbA==", - "dev": true, + "version": "2.1.10", + "resolved": "https://registry.npmjs.org/@ionic/utils-process/-/utils-process-2.1.10.tgz", + "integrity": "sha512-mZ7JEowcuGQK+SKsJXi0liYTcXd2bNMR3nE0CyTROpMECUpJeAvvaBaPGZf5ERQUPeWBVuwqAqjUmIdxhz5bxw==", "license": "MIT", "dependencies": { - "@ionic/utils-object": "2.1.6", - "@ionic/utils-terminal": "2.3.4", + "@ionic/utils-object": "2.1.5", + "@ionic/utils-terminal": "2.3.3", "debug": "^4.0.0", "signal-exit": "^3.0.3", "tree-kill": "^1.2.2", "tslib": "^2.0.1" }, "engines": { - "node": ">=16.0.0" + "node": ">=10.3.0" } }, "node_modules/@ionic/utils-process/node_modules/@ionic/utils-terminal": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/@ionic/utils-terminal/-/utils-terminal-2.3.4.tgz", - "integrity": "sha512-cEiMFl3jklE0sW60r8JHH3ijFTwh/jkdEKWbylSyExQwZ8pPuwoXz7gpkWoJRLuoRHHSvg+wzNYyPJazIHfoJA==", - "dev": true, + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@ionic/utils-terminal/-/utils-terminal-2.3.3.tgz", + "integrity": "sha512-RnuSfNZ5fLEyX3R5mtcMY97cGD1A0NVBbarsSQ6yMMfRJ5YHU7hHVyUfvZeClbqkBC/pAqI/rYJuXKCT9YeMCQ==", "license": "MIT", "dependencies": { "@types/slice-ansi": "^4.0.0", @@ -788,48 +1386,66 @@ "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">=16.0.0" + "node": ">=10.3.0" } }, + "node_modules/@ionic/utils-process/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, "node_modules/@ionic/utils-stream": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/@ionic/utils-stream/-/utils-stream-3.1.6.tgz", - "integrity": "sha512-4+Kitey1lTA1yGtnigeYNhV/0tggI3lWBMjC7tBs1K9GXa/q7q4CtOISppdh8QgtOhrhAXS2Igp8rbko/Cj+lA==", - "dev": true, + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@ionic/utils-stream/-/utils-stream-3.1.5.tgz", + "integrity": "sha512-hkm46uHvEC05X/8PHgdJi4l4zv9VQDELZTM+Kz69odtO9zZYfnt8DkfXHJqJ+PxmtiE5mk/ehJWLnn/XAczTUw==", "license": "MIT", "dependencies": { "debug": "^4.0.0", "tslib": "^2.0.1" }, "engines": { - "node": ">=16.0.0" + "node": ">=10.3.0" } }, "node_modules/@ionic/utils-subprocess": { - "version": "2.1.14", - "resolved": "https://registry.npmjs.org/@ionic/utils-subprocess/-/utils-subprocess-2.1.14.tgz", - "integrity": "sha512-nGYvyGVjU0kjPUcSRFr4ROTraT3w/7r502f5QJEsMRKTqa4eEzCshtwRk+/mpASm0kgBN5rrjYA5A/OZg8ahqg==", - "dev": true, + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/@ionic/utils-subprocess/-/utils-subprocess-2.1.11.tgz", + "integrity": "sha512-6zCDixNmZCbMCy5np8klSxOZF85kuDyzZSTTQKQP90ZtYNCcPYmuFSzaqDwApJT4r5L3MY3JrqK1gLkc6xiUPw==", "license": "MIT", "dependencies": { - "@ionic/utils-array": "2.1.6", - "@ionic/utils-fs": "3.1.7", - "@ionic/utils-process": "2.1.11", - "@ionic/utils-stream": "3.1.6", - "@ionic/utils-terminal": "2.3.4", + "@ionic/utils-array": "2.1.5", + "@ionic/utils-fs": "3.1.6", + "@ionic/utils-process": "2.1.10", + "@ionic/utils-stream": "3.1.5", + "@ionic/utils-terminal": "2.3.3", "cross-spawn": "^7.0.3", "debug": "^4.0.0", "tslib": "^2.0.1" }, "engines": { - "node": ">=16.0.0" + "node": ">=10.3.0" + } + }, + "node_modules/@ionic/utils-subprocess/node_modules/@ionic/utils-fs": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@ionic/utils-fs/-/utils-fs-3.1.6.tgz", + "integrity": "sha512-eikrNkK89CfGPmexjTfSWl4EYqsPSBh0Ka7by4F0PLc1hJZYtJxUZV3X4r5ecA8ikjicUmcbU7zJmAjmqutG/w==", + "license": "MIT", + "dependencies": { + "@types/fs-extra": "^8.0.0", + "debug": "^4.0.0", + "fs-extra": "^9.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=10.3.0" } }, "node_modules/@ionic/utils-subprocess/node_modules/@ionic/utils-terminal": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/@ionic/utils-terminal/-/utils-terminal-2.3.4.tgz", - "integrity": "sha512-cEiMFl3jklE0sW60r8JHH3ijFTwh/jkdEKWbylSyExQwZ8pPuwoXz7gpkWoJRLuoRHHSvg+wzNYyPJazIHfoJA==", - "dev": true, + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@ionic/utils-terminal/-/utils-terminal-2.3.3.tgz", + "integrity": "sha512-RnuSfNZ5fLEyX3R5mtcMY97cGD1A0NVBbarsSQ6yMMfRJ5YHU7hHVyUfvZeClbqkBC/pAqI/rYJuXKCT9YeMCQ==", "license": "MIT", "dependencies": { "@types/slice-ansi": "^4.0.0", @@ -843,14 +1459,19 @@ "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">=16.0.0" + "node": ">=10.3.0" } }, + "node_modules/@ionic/utils-subprocess/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, "node_modules/@ionic/utils-terminal": { "version": "2.3.5", "resolved": "https://registry.npmjs.org/@ionic/utils-terminal/-/utils-terminal-2.3.5.tgz", "integrity": "sha512-3cKScz9Jx2/Pr9ijj1OzGlBDfcmx7OMVBt4+P1uRR0SSW4cm1/y3Mo4OY3lfkuaYifMNBW8Wz6lQHbs1bihr7A==", - "dev": true, "license": "MIT", "dependencies": { "@types/slice-ansi": "^4.0.0", @@ -867,16 +1488,31 @@ "node": ">=16.0.0" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "node_modules/@ionic/utils-terminal/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", "dev": true, "license": "MIT", - "optional": true, - "peer": true, "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, @@ -886,25 +1522,10 @@ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "license": "MIT", - "optional": true, - "peer": true, "engines": { "node": ">=6.0.0" } }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", - "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", @@ -912,13 +1533,11 @@ "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.30", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz", - "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==", + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, "license": "MIT", - "optional": true, - "peer": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -962,6 +1581,20 @@ "node": ">= 8" } }, + "node_modules/@polka/url": { + "version": "1.0.0-next.29", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", + "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.29", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.29.tgz", + "integrity": "sha512-NIJgOsMjbxAXvoGq/X0gD7VPMQ8j9g0BiDaNjVNVjvl+iKXxL3Jre0v31RmBYeLEmkbj2s02v8vFTbUXi5XS2Q==", + "dev": true, + "license": "MIT" + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.52.4", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.4.tgz", @@ -1270,6 +1903,33 @@ "win32" ] }, + "node_modules/@sec-ant/readable-stream": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", + "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", + "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@tsconfig/node22": { + "version": "22.0.2", + "resolved": "https://registry.npmjs.org/@tsconfig/node22/-/node22-22.0.2.tgz", + "integrity": "sha512-Kmwj4u8sDRDrMYRoN9FDEcXD8UpBSaPQQ24Gz+Gamqfm7xxn+GBR7ge/Z7pK8OXNGyUzbSwJj+TH6B+DS/epyA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -1281,7 +1941,6 @@ "version": "8.1.5", "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.5.tgz", "integrity": "sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ==", - "dev": true, "license": "MIT", "dependencies": { "@types/node": "*" @@ -1295,148 +1954,175 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "20.19.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.21.tgz", - "integrity": "sha512-CsGG2P3I5y48RPMfprQGfy4JPRZ6csfC3ltBZSRItG3ngggmNY/qs2uZKp4p9VbrpqNNSMzUZNFZKzgOGnd/VA==", - "dev": true, + "version": "22.18.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.10.tgz", + "integrity": "sha512-anNG/V/Efn/YZY4pRzbACnKxNKoBng2VTFydVu8RRs5hQjikP8CQfaeAV59VFSCzKNp90mXiVXW2QzV56rwMrg==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" } }, - "node_modules/@types/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/slice-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/slice-ansi/-/slice-ansi-4.0.0.tgz", "integrity": "sha512-+OpjSaq85gvlZAYINyzKpLeiFkSC4EsC6IIiT6v6TLSU5k5U83fHGj9Lel8oKEXM0HqgrMVCjXPDPVICtxF7EQ==", - "dev": true, "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", - "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.1.tgz", + "integrity": "sha512-rUsLh8PXmBjdiPY+Emjz9NX2yHvhS11v0SR6xNJkm5GM1MO9ea/1GoDKlHHZGrOJclL/cZ2i/vRUYVtjRhrHVQ==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/type-utils": "6.21.0", - "@typescript-eslint/utils": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", - "debug": "^4.3.4", + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.46.1", + "@typescript-eslint/type-utils": "8.46.1", + "@typescript-eslint/utils": "8.46.1", + "@typescript-eslint/visitor-keys": "8.46.1", "graphemer": "^1.4.0", - "ignore": "^5.2.4", + "ignore": "^7.0.0", "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "ts-api-utils": "^2.1.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@typescript-eslint/parser": "^8.46.1", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" } }, "node_modules/@typescript-eslint/parser": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", - "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.1.tgz", + "integrity": "sha512-6JSSaBZmsKvEkbRUkf7Zj7dru/8ZCrJxAqArcLaVMee5907JdtEbKGsZ7zNiIm/UAkpGUkaSMZEXShnN2D1HZA==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", + "@typescript-eslint/scope-manager": "8.46.1", + "@typescript-eslint/types": "8.46.1", + "@typescript-eslint/typescript-estree": "8.46.1", + "@typescript-eslint/visitor-keys": "8.46.1", "debug": "^4.3.4" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.1.tgz", + "integrity": "sha512-FOIaFVMHzRskXr5J4Jp8lFVV0gz5ngv3RHmn+E4HYxSJ3DgDzU7fVI1/M7Ijh1zf6S7HIoaIOtln1H5y8V+9Zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.46.1", + "@typescript-eslint/types": "^8.46.1", + "debug": "^4.3.4" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "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": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.1.tgz", + "integrity": "sha512-weL9Gg3/5F0pVQKiF8eOXFZp8emqWzZsOJuWRUNtHT+UNV2xSJegmpCNQHy37aEQIbToTq7RHKhWvOsmbM680A==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" + "@typescript-eslint/types": "8.46.1", + "@typescript-eslint/visitor-keys": "8.46.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.1.tgz", + "integrity": "sha512-X88+J/CwFvlJB+mK09VFqx5FE4H5cXD+H/Bdza2aEWkSb8hnWIQorNcscRl4IEo1Cz9VI/+/r/jnGWkbWPx54g==", + "dev": true, + "license": "MIT", "engines": { - "node": "^16.0.0 || >=18.0.0" + "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": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", - "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.1.tgz", + "integrity": "sha512-+BlmiHIiqufBxkVnOtFwjah/vrkF4MtKKvpXrKSPLCkCtAp8H01/VV43sfqA98Od7nJpDcFnkwgyfQbOG0AMvw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "6.21.0", - "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/types": "8.46.1", + "@typescript-eslint/typescript-estree": "8.46.1", + "@typescript-eslint/utils": "8.46.1", "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" + "ts-api-utils": "^2.1.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", - "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.1.tgz", + "integrity": "sha512-C+soprGBHwWBdkDpbaRC4paGBrkIXxVlNohadL5o0kfhsXqOC6GYH2S/Obmig+I0HTDl8wMaRySwrfrXVP8/pQ==", "dev": true, "license": "MIT", "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -1444,144 +2130,186 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", - "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.1.tgz", + "integrity": "sha512-uIifjT4s8cQKFQ8ZBXXyoUODtRoAd7F7+G8MKmtzj17+1UbdzFl52AzRyZRyKqPHhgzvXunnSckVu36flGy8cg==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", + "@typescript-eslint/project-service": "8.46.1", + "@typescript-eslint/tsconfig-utils": "8.46.1", + "@typescript-eslint/types": "8.46.1", + "@typescript-eslint/visitor-keys": "8.46.1", "debug": "^4.3.4", - "globby": "^11.1.0", + "fast-glob": "^3.3.2", "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", - "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.1.tgz", + "integrity": "sha512-vkYUy6LdZS7q1v/Gxb2Zs7zziuXN0wxqsetJdeZdRe/f5dwJFglmuvZBfTUivCtjH725C1jWCDfpadadD95EDQ==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", - "semver": "^7.5.4" + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.46.1", + "@typescript-eslint/types": "8.46.1", + "@typescript-eslint/typescript-estree": "8.46.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", - "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.1.tgz", + "integrity": "sha512-ptkmIf2iDkNUjdeu2bQqhFPV1m6qTnFFjg7PPDjxKWaMaP0Z6I9l30Jr3g5QqbZGdw8YdYvLp+XnqnWWZOg/NA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "6.21.0", - "eslint-visitor-keys": "^3.4.1" + "@typescript-eslint/types": "8.46.1", + "eslint-visitor-keys": "^4.2.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-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==", + "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": "ISC" + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } }, "node_modules/@vitejs/plugin-vue": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.6.2.tgz", - "integrity": "sha512-kqf7SGFoG+80aZG6Pf+gsZIVvGSCKE98JbiWqcCV9cThtg91Jav0yvYFC9Zb+jKetNGF6ZKeoaxgZfND21fWKw==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.1.tgz", + "integrity": "sha512-+MaE752hU0wfPFJEUAIxqw18+20euHHdxVtMvbFcOEpjEyfqXH/5DCoTHiVJ0J29EhTJdoTkjEv5YBKU9dnoTw==", "dev": true, "license": "MIT", + "dependencies": { + "@rolldown/pluginutils": "1.0.0-beta.29" + }, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": "^20.19.0 || >=22.12.0" }, "peerDependencies": { - "vite": "^4.0.0 || ^5.0.0", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0", "vue": "^3.2.25" } }, "node_modules/@volar/language-core": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-1.11.1.tgz", - "integrity": "sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw==", + "version": "2.4.23", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.23.tgz", + "integrity": "sha512-hEEd5ET/oSmBC6pi1j6NaNYRWoAiDhINbT8rmwtINugR39loROSlufGdYMF9TaKGfz+ViGs1Idi3mAhnuPcoGQ==", "dev": true, "license": "MIT", "dependencies": { - "@volar/source-map": "1.11.1" + "@volar/source-map": "2.4.23" } }, "node_modules/@volar/source-map": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-1.11.1.tgz", - "integrity": "sha512-hJnOnwZ4+WT5iupLRnuzbULZ42L7BWWPMmruzwtLhJfpDVoZLjNBxHDi2sY2bgZXCKlpU5XcsMFoYrsQmPhfZg==", + "version": "2.4.23", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.23.tgz", + "integrity": "sha512-Z1Uc8IB57Lm6k7q6KIDu/p+JWtf3xsXJqAX/5r18hYOTpJyBn0KXUR8oTJ4WFYOcDzWC9n3IflGgHowx6U6z9Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@volar/typescript": { + "version": "2.4.23", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.23.tgz", + "integrity": "sha512-lAB5zJghWxVPqfcStmAP1ZqQacMpe90UrP5RJ3arDyrhy4aCUQqmxPPLB2PWDKugvylmO41ljK7vZ+t6INMTag==", "dev": true, "license": "MIT", "dependencies": { - "muggle-string": "^0.3.1" + "@volar/language-core": "2.4.23", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" } }, - "node_modules/@volar/typescript": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-1.11.1.tgz", - "integrity": "sha512-iU+t2mas/4lYierSnoFOeRFQUhAEMgsFuQxoxvwn5EdQopw43j+J27a4lt9LMInx1gLJBC6qL14WYGlgymaSMQ==", + "node_modules/@vue/babel-helper-vue-transform-on": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.5.0.tgz", + "integrity": "sha512-0dAYkerNhhHutHZ34JtTl2czVQHUNWv6xEbkdF5W+Yrv5pCWsqjeORdOgbtW2I9gWlt+wBmVn+ttqN9ZxR5tzA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vue/babel-plugin-jsx": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.5.0.tgz", + "integrity": "sha512-mneBhw1oOqCd2247O0Yw/mRwC9jIGACAJUlawkmMBiNmL4dGA2eMzuNZVNqOUfYTa6vqmND4CtOPzmEEEqLKFw==", "dev": true, "license": "MIT", "dependencies": { - "@volar/language-core": "1.11.1", - "path-browserify": "^1.0.1" + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.0", + "@babel/types": "^7.28.2", + "@vue/babel-helper-vue-transform-on": "1.5.0", + "@vue/babel-plugin-resolve-type": "1.5.0", + "@vue/shared": "^3.5.18" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + } + } + }, + "node_modules/@vue/babel-plugin-resolve-type": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-resolve-type/-/babel-plugin-resolve-type-1.5.0.tgz", + "integrity": "sha512-Wm/60o+53JwJODm4Knz47dxJnLDJ9FnKnGZJbUUf8nQRAtt6P+undLUAVU3Ha33LxOJe6IPoifRQ6F/0RrU31w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/parser": "^7.28.0", + "@vue/compiler-sfc": "^3.5.18" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, "node_modules/@vue/compiler-core": { @@ -1597,18 +2325,6 @@ "source-map-js": "^1.2.1" } }, - "node_modules/@vue/compiler-core/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, "node_modules/@vue/compiler-dom": { "version": "3.5.22", "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.22.tgz", @@ -1647,29 +2363,127 @@ } }, "node_modules/@vue/devtools-api": { - "version": "6.6.4", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", - "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "version": "7.7.7", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.7.tgz", + "integrity": "sha512-lwOnNBH2e7x1fIIbVT7yF5D+YWhqELm55/4ZKf45R9T8r9dE2AIOy8HKjfqzGsoTHFbWbr337O4E0A0QADnjBg==", + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^7.7.7" + } + }, + "node_modules/@vue/devtools-core": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@vue/devtools-core/-/devtools-core-8.0.2.tgz", + "integrity": "sha512-V7eKTTHoS6KfK8PSGMLZMhGv/9yNDrmv6Qc3r71QILulnzPnqK2frsTyx3e2MrhdUZnENPEm6hcb4z0GZOqNhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^8.0.2", + "@vue/devtools-shared": "^8.0.2", + "mitt": "^3.0.1", + "nanoid": "^5.1.5", + "pathe": "^2.0.3", + "vite-hot-client": "^2.1.0" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/@vue/devtools-core/node_modules/@vue/devtools-kit": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-8.0.2.tgz", + "integrity": "sha512-yjZKdEmhJzQqbOh4KFBfTOQjDPMrjjBNCnHBvnTGJX+YLAqoUtY2J+cg7BE+EA8KUv8LprECq04ts75wCoIGWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^8.0.2", + "birpc": "^2.5.0", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^2.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.2" + } + }, + "node_modules/@vue/devtools-core/node_modules/@vue/devtools-shared": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-8.0.2.tgz", + "integrity": "sha512-mLU0QVdy5Lp40PMGSixDw/Kbd6v5dkQXltd2r+mdVQV7iUog2NlZuLxFZApFZ/mObUBDhoCpf0T3zF2FWWdeHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "rfdc": "^1.4.1" + } + }, + "node_modules/@vue/devtools-core/node_modules/nanoid": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.6.tgz", + "integrity": "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.js" + }, + "engines": { + "node": "^18 || >=20" + } + }, + "node_modules/@vue/devtools-core/node_modules/perfect-debounce": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.0.0.tgz", + "integrity": "sha512-fkEH/OBiKrqqI/yIgjR92lMfs2K8105zt/VT6+7eTjNwisrsh47CeIED9z58zI7DfKdH3uHAn25ziRZn3kgAow==", + "dev": true, "license": "MIT" }, + "node_modules/@vue/devtools-kit": { + "version": "7.7.7", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.7.tgz", + "integrity": "sha512-wgoZtxcTta65cnZ1Q6MbAfePVFxfM+gq0saaeytoph7nEa7yMXoi6sCPy4ufO111B9msnw0VOWjPEFCXuAKRHA==", + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^7.7.7", + "birpc": "^2.3.0", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.2" + } + }, + "node_modules/@vue/devtools-shared": { + "version": "7.7.7", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.7.tgz", + "integrity": "sha512-+udSj47aRl5aKb0memBvcUG9koarqnxNM5yjuREvqwK6T3ap4mn3Zqqc17QrBFTqSMjr3HK1cvStEZpMDpfdyw==", + "license": "MIT", + "dependencies": { + "rfdc": "^1.4.1" + } + }, "node_modules/@vue/eslint-config-typescript": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-12.0.0.tgz", - "integrity": "sha512-StxLFet2Qe97T8+7L8pGlhYBBr8Eg05LPuTDVopQV6il+SK6qqom59BA/rcFipUef2jD8P2X44Vd8tMFytfvlg==", + "version": "14.6.0", + "resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-14.6.0.tgz", + "integrity": "sha512-UpiRY/7go4Yps4mYCjkvlIbVWmn9YvPGQDxTAlcKLphyaD77LjIu3plH4Y9zNT0GB4f3K5tMmhhtRhPOgrQ/bQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "^6.7.0", - "@typescript-eslint/parser": "^6.7.0", - "vue-eslint-parser": "^9.3.1" + "@typescript-eslint/utils": "^8.35.1", + "fast-glob": "^3.3.3", + "typescript-eslint": "^8.35.1", + "vue-eslint-parser": "^10.2.0" }, "engines": { - "node": "^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "peerDependencies": { - "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0", - "eslint-plugin-vue": "^9.0.0", - "typescript": "*" + "eslint": "^9.10.0", + "eslint-plugin-vue": "^9.28.0 || ^10.0.0", + "typescript": ">=4.8.4" }, "peerDependenciesMeta": { "typescript": { @@ -1678,21 +2492,19 @@ } }, "node_modules/@vue/language-core": { - "version": "1.8.27", - "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-1.8.27.tgz", - "integrity": "sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-3.1.1.tgz", + "integrity": "sha512-qjMY3Q+hUCjdH+jLrQapqgpsJ0rd/2mAY02lZoHG3VFJZZZKLjAlV+Oo9QmWIT4jh8+Rx8RUGUi++d7T9Wb6Mw==", "dev": true, "license": "MIT", "dependencies": { - "@volar/language-core": "~1.11.1", - "@volar/source-map": "~1.11.1", - "@vue/compiler-dom": "^3.3.0", - "@vue/shared": "^3.3.0", - "computeds": "^0.0.1", - "minimatch": "^9.0.3", - "muggle-string": "^0.3.1", + "@volar/language-core": "2.4.23", + "@vue/compiler-dom": "^3.5.0", + "@vue/shared": "^3.5.0", + "alien-signals": "^3.0.0", + "muggle-string": "^0.4.1", "path-browserify": "^1.0.1", - "vue-template-compiler": "^2.7.14" + "picomatch": "^4.0.2" }, "peerDependencies": { "typescript": "*" @@ -1703,20 +2515,17 @@ } } }, - "node_modules/@vue/language-core/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "node_modules/@vue/language-core/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": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, + "license": "MIT", "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/@vue/reactivity": { @@ -1770,17 +2579,28 @@ "license": "MIT" }, "node_modules/@vue/tsconfig": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@vue/tsconfig/-/tsconfig-0.5.1.tgz", - "integrity": "sha512-VcZK7MvpjuTPx2w6blwnwZAu5/LgBUtejFOi3pPGQFXQN5Ela03FUtd2Qtg4yWGGissVL0dr6Ro1LfOFh+PCuQ==", + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@vue/tsconfig/-/tsconfig-0.8.1.tgz", + "integrity": "sha512-aK7feIWPXFSUhsCP9PFqPyFOcz4ENkb8hZ2pneL6m2UjCkccvaOhC/5KCKluuBufvp2KzkbdA2W2pk20vLzu3g==", "dev": true, - "license": "MIT" + "license": "MIT", + "peerDependencies": { + "typescript": "5.x", + "vue": "^3.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "vue": { + "optional": true + } + } }, "node_modules/@xmldom/xmldom": { "version": "0.8.11", "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.11.tgz", "integrity": "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==", - "dev": true, "license": "MIT", "engines": { "node": ">=10.0.0" @@ -1809,11 +2629,34 @@ "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/alien-signals": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/alien-signals/-/alien-signals-3.0.0.tgz", + "integrity": "sha512-JHoRJf18Y6HN4/KZALr3iU+0vW9LKG+8FMThQlbn4+gv8utsLIkwpomjElGPccGeNwh0FI2HN6BLnyFLo6OyLQ==", + "dev": true, + "license": "MIT" + }, "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" @@ -1823,7 +2666,6 @@ "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" @@ -1835,6 +2677,16 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/ansis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.2.0.tgz", + "integrity": "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -1842,21 +2694,10 @@ "dev": true, "license": "Python-2.0" }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -1866,7 +2707,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true, "license": "ISC", "engines": { "node": ">= 4.0.0" @@ -1876,14 +2716,12 @@ "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/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, "funding": [ { "type": "github", @@ -1900,16 +2738,34 @@ ], "license": "MIT" }, + "node_modules/baseline-browser-mapping": { + "version": "2.8.16", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.16.tgz", + "integrity": "sha512-OMu3BGQ4E7P1ErFsIPpbJh0qvDudM/UuJeHgkAvfWe+0HFJCXh+t/l8L6fVLR55RI/UbKrVLnAXZSVwd9ysWYw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, "node_modules/big-integer": { "version": "1.6.52", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", - "dev": true, "license": "Unlicense", "engines": { "node": ">=0.6" } }, + "node_modules/birpc": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.6.1.tgz", + "integrity": "sha512-LPnFhlDpdSH6FJhJyn4M0kFO7vtQ5iPw24FnG0y21q09xC7e8+1LeR31S1MAIrDAHp4m7aas4bEkTDTvMAtebQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -1921,7 +2777,6 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.2.tgz", "integrity": "sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ==", - "dev": true, "license": "MIT", "dependencies": { "big-integer": "1.6.x" @@ -1934,7 +2789,6 @@ "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" @@ -1953,24 +2807,64 @@ "node": ">=8" } }, + "node_modules/browserslist": { + "version": "4.26.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.3.tgz", + "integrity": "sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.8.9", + "caniuse-lite": "^1.0.30001746", + "electron-to-chromium": "^1.5.227", + "node-releases": "^2.0.21", + "update-browserslist-db": "^1.1.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, "node_modules/buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, "license": "MIT", "engines": { "node": "*" } }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", "dev": true, "license": "MIT", - "optional": true, - "peer": true + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/callsites": { "version": "3.1.0", @@ -1982,6 +2876,27 @@ "node": ">=6" } }, + "node_modules/caniuse-lite": { + "version": "1.0.30001750", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001750.tgz", + "integrity": "sha512-cuom0g5sdX6rw00qOoLNSFCJ9/mYIsuSOA+yzpDw8eopiFqcVwQvZHqov0vmEighRxX++cfC0Vg1G+1Iy/mSpQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -2003,7 +2918,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, "license": "ISC", "engines": { "node": ">=10" @@ -2013,7 +2927,6 @@ "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" @@ -2026,26 +2939,17 @@ "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/commander": { "version": "9.5.0", "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", - "dev": true, "license": "MIT", "engines": { "node": "^12.20.0 || >=14" } }, - "node_modules/computeds": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/computeds/-/computeds-0.0.1.tgz", - "integrity": "sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==", - "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", @@ -2053,11 +2957,32 @@ "dev": true, "license": "MIT" }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/copy-anything": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz", + "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==", + "license": "MIT", + "dependencies": { + "is-what": "^4.1.8" + }, + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, "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", @@ -2087,18 +3012,20 @@ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", "license": "MIT" }, - "node_modules/de-indent": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", - "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", - "dev": true, - "license": "MIT" + "node_modules/date-fns": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", + "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } }, "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", - "dev": true, + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -2119,47 +3046,60 @@ "dev": true, "license": "MIT" }, - "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "node_modules/default-browser": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", + "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", "dev": true, "license": "MIT", + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "node_modules/default-browser-id": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", + "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", "dev": true, "license": "MIT", - "dependencies": { - "path-type": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/doctrine": { + "node_modules/define-lazy-prop": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, + "license": "MIT", "engines": { - "node": ">=6.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/electron-to-chromium": { + "version": "1.5.237", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.237.tgz", + "integrity": "sha512-icUt1NvfhGLar5lSWH3tHNzablaA5js3HVHacQimfP8ViEBOQv+L7DKEuHdbTZ0SKCO1ogTJTIL1Gwk9S6Qvcg==", + "dev": true, + "license": "ISC" + }, "node_modules/elementtree": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/elementtree/-/elementtree-0.1.7.tgz", "integrity": "sha512-wkgGT6kugeQk/P6VZ/f4T+4HB41BVgNBq5CDIZVbQ02nvTVqAiVTbskxxu3eA/X96lMlfYOwnLQpN2v5E1zDEg==", - "dev": true, "license": "Apache-2.0", "dependencies": { "sax": "1.1.4" @@ -2172,23 +3112,43 @@ "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/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/env-paths": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, + "node_modules/error-stack-parser-es": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz", + "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.11.tgz", + "integrity": "sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -2196,32 +3156,45 @@ "esbuild": "bin/esbuild" }, "engines": { - "node": ">=12" + "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" + "@esbuild/aix-ppc64": "0.25.11", + "@esbuild/android-arm": "0.25.11", + "@esbuild/android-arm64": "0.25.11", + "@esbuild/android-x64": "0.25.11", + "@esbuild/darwin-arm64": "0.25.11", + "@esbuild/darwin-x64": "0.25.11", + "@esbuild/freebsd-arm64": "0.25.11", + "@esbuild/freebsd-x64": "0.25.11", + "@esbuild/linux-arm": "0.25.11", + "@esbuild/linux-arm64": "0.25.11", + "@esbuild/linux-ia32": "0.25.11", + "@esbuild/linux-loong64": "0.25.11", + "@esbuild/linux-mips64el": "0.25.11", + "@esbuild/linux-ppc64": "0.25.11", + "@esbuild/linux-riscv64": "0.25.11", + "@esbuild/linux-s390x": "0.25.11", + "@esbuild/linux-x64": "0.25.11", + "@esbuild/netbsd-arm64": "0.25.11", + "@esbuild/netbsd-x64": "0.25.11", + "@esbuild/openbsd-arm64": "0.25.11", + "@esbuild/openbsd-x64": "0.25.11", + "@esbuild/openharmony-arm64": "0.25.11", + "@esbuild/sunos-x64": "0.25.11", + "@esbuild/win32-arm64": "0.25.11", + "@esbuild/win32-ia32": "0.25.11", + "@esbuild/win32-x64": "0.25.11" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" } }, "node_modules/escape-string-regexp": { @@ -2238,204 +3211,146 @@ } }, "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.", + "version": "9.37.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.37.0.tgz", + "integrity": "sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==", "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", + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.4.0", + "@eslint/core": "^0.16.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.37.0", + "@eslint/plugin-kit": "^0.4.0", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "cross-spawn": "^7.0.6", "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", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "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" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-plugin-vue": { - "version": "9.33.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.33.0.tgz", - "integrity": "sha512-174lJKuNsuDIlLpjeXc5E2Tss8P44uIimAfGD0b90k0NoirJqpG7stLuU9Vp/9ioTOrQdWVREc4mRd1BD+CvGw==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-10.4.0.tgz", + "integrity": "sha512-K6tP0dW8FJVZLQxa2S7LcE1lLw3X8VvB3t887Q6CLrFVxHYBXGANbXvwNzYIu6Ughx1bSJ5BDT0YB3ybPT39lw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "globals": "^13.24.0", "natural-compare": "^1.4.0", "nth-check": "^2.1.1", "postcss-selector-parser": "^6.0.15", "semver": "^7.6.3", - "vue-eslint-parser": "^9.4.3", "xml-name-validator": "^4.0.0" }, "engines": { - "node": "^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "peerDependencies": { - "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint/node_modules/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" + "@typescript-eslint/parser": "^7.0.0 || ^8.0.0", + "eslint": "^8.57.0 || ^9.0.0", + "vue-eslint-parser": "^10.0.0" }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/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" + "peerDependenciesMeta": { + "@typescript-eslint/parser": { + "optional": true + } } }, - "node_modules/eslint/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==", + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": ">=10" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "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": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, + "license": "Apache-2.0", "engines": { - "node": ">=10.13.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/eslint/node_modules/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==", + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { - "p-locate": "^5.0.0" - }, + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=10" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/minimatch": { @@ -2451,51 +3366,32 @@ "node": "*" } }, - "node_modules/eslint/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/eslint/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==", + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "p-limit": "^3.0.2" + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" }, "engines": { - "node": ">=10" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "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==", + "node_modules/espree/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": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, + "license": "Apache-2.0", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -2514,16 +3410,6 @@ "node": ">=0.10" } }, - "node_modules/esquery/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/esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", @@ -2537,7 +3423,7 @@ "node": ">=4.0" } }, - "node_modules/esrecurse/node_modules/estraverse": { + "node_modules/estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", @@ -2563,6 +3449,39 @@ "node": ">=0.10.0" } }, + "node_modules/execa": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-9.6.0.tgz", + "integrity": "sha512-jpWzZ1ZhwUmeWRhS7Qv3mhpOhLfwI+uAX4e5fOcXqwMR7EcJ0pj2kV1CVzHVMX/LphnKWD3LObjZCoJ71lKpHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^4.0.0", + "cross-spawn": "^7.0.6", + "figures": "^6.1.0", + "get-stream": "^9.0.0", + "human-signals": "^8.0.1", + "is-plain-obj": "^4.1.0", + "is-stream": "^4.0.1", + "npm-run-path": "^6.0.0", + "pretty-ms": "^9.2.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^4.0.0", + "yoctocolors": "^2.1.1" + }, + "engines": { + "node": "^18.19.0 || >=20.5.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/facing-metadata": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/facing-metadata/-/facing-metadata-2.0.3.tgz", + "integrity": "sha512-cznIFYEbjy5LCph7aolYr6+5B1PzJAPsW4q3xdsmJDdZgsepFCBq4vZkBgCGt2LZZKNwji0Qt1xU24JOqg/6xQ==", + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2587,6 +3506,19 @@ "node": ">=8.6.0" } }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -2615,114 +3547,82 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, "license": "MIT", "dependencies": { "pend": "~1.2.0" } }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "node_modules/figures": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", + "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^3.0.4" + "is-unicode-supported": "^2.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "license": "MIT", "dependencies": { - "to-regex-range": "^5.0.1" + "flat-cache": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=16.0.0" } }, - "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==", + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "license": "MIT", "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "to-regex-range": "^5.0.1" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=8" } }, - "node_modules/flat-cache/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==", + "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": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/flat-cache/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" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": "*" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/flat-cache/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "flatted": "^3.2.9", + "keyv": "^4.5.4" }, "engines": { - "node": "*" - } - }, - "node_modules/flat-cache/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": ">=16" } }, "node_modules/flatted": { @@ -2736,7 +3636,6 @@ "version": "9.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, "license": "MIT", "dependencies": { "at-least-node": "^1.0.0", @@ -2752,7 +3651,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, "license": "ISC", "dependencies": { "minipass": "^3.0.0" @@ -2765,7 +3663,6 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, "license": "ISC", "dependencies": { "yallist": "^4.0.0" @@ -2774,11 +3671,16 @@ "node": ">=8" } }, + "node_modules/fs-minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true, "license": "ISC" }, "node_modules/fsevents": { @@ -2796,11 +3698,37 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-stream": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", + "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sec-ant/readable-stream": "^0.4.1", + "is-stream": "^4.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/glob": { "version": "9.3.5", "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", - "dev": true, "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", @@ -2816,50 +3744,41 @@ } }, "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "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.1" + "is-glob": "^4.0.3" }, "engines": { - "node": ">= 6" + "node": ">=10.13.0" } }, - "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", + "node_modules/glob/node_modules/minimatch": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", + "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "license": "ISC", "dependencies": { - "type-fest": "^0.20.2" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2869,7 +3788,6 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, "license": "ISC" }, "node_modules/graphemer": { @@ -2889,14 +3807,20 @@ "node": ">=8" } }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "license": "MIT" + }, + "node_modules/human-signals": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz", + "integrity": "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==", "dev": true, - "license": "MIT", - "bin": { - "he": "bin/he" + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" } }, "node_modules/ignore": { @@ -2917,23 +3841,13 @@ "license": "MIT", "dependencies": { "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-fresh/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", + "resolve-from": "^4.0.0" + }, "engines": { - "node": ">=4" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/imurmurhash": { @@ -2946,46 +3860,32 @@ "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/ini": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz", "integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==", - "dev": true, "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", "dev": true, "license": "MIT", "bin": { "is-docker": "cli.js" }, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -3005,7 +3905,6 @@ "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" @@ -3024,6 +3923,25 @@ "node": ">=0.10.0" } }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -3034,36 +3952,96 @@ "node": ">=0.12.0" } }, - "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==", + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-stream": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", + "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-unicode-supported": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-what": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz", + "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==", + "license": "MIT", + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" } }, "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", "dev": true, "license": "MIT", "dependencies": { - "is-docker": "^2.0.0" + "is-inside-container": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, "license": "ISC" }, + "node_modules/jiti": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -3077,6 +4055,19 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -3084,6 +4075,23 @@ "dev": true, "license": "MIT" }, + "node_modules/json-parse-even-better-errors": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-4.0.0.tgz", + "integrity": "sha512-lR4MXjGNgkJc7tkQ97kb2nuEMnNCyU//XYVH0MKTGcXEiSudQ5MKGKen3C5QubYy0vmq+JGitUg92uuywGEwIA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "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", @@ -3091,11 +4099,23 @@ "dev": true, "license": "MIT" }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/jsonfile": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, "license": "MIT", "dependencies": { "universalify": "^2.0.0" @@ -3118,12 +4138,18 @@ "version": "4.1.5", "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, + "node_modules/kolorist": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", + "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==", + "dev": true, + "license": "MIT" + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -3138,12 +4164,21 @@ "node": ">= 0.8.0" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "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" + "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", @@ -3153,11 +4188,14 @@ "license": "MIT" }, "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==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, - "license": "ISC" + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } }, "node_modules/magic-string": { "version": "0.30.19", @@ -3168,6 +4206,15 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -3193,9 +4240,9 @@ } }, "node_modules/minimatch": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", - "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "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": { @@ -3212,7 +4259,6 @@ "version": "4.2.8", "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", - "dev": true, "license": "ISC", "engines": { "node": ">=8" @@ -3222,7 +4268,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, "license": "MIT", "dependencies": { "minipass": "^3.0.0", @@ -3236,7 +4281,6 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, "license": "ISC", "dependencies": { "yallist": "^4.0.0" @@ -3245,11 +4289,22 @@ "node": ">=8" } }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "license": "MIT" + }, "node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, "license": "MIT", "bin": { "mkdirp": "bin/cmd.js" @@ -3258,17 +4313,26 @@ "node": ">=10" } }, + "node_modules/mrmime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "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/muggle-string": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.3.1.tgz", - "integrity": "sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", "dev": true, "license": "MIT" }, @@ -3294,7 +4358,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/native-run/-/native-run-2.0.1.tgz", "integrity": "sha512-XfG1FBZLM50J10xH9361whJRC9SHZ0Bub4iNRhhI61C8Jv0e1ud19muex6sNKB51ibQNUJNuYn25MuYET/rE6w==", - "dev": true, "license": "MIT", "dependencies": { "@ionic/utils-fs": "^3.1.7", @@ -3323,6 +4386,132 @@ "dev": true, "license": "MIT" }, + "node_modules/node-releases": { + "version": "2.0.23", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.23.tgz", + "integrity": "sha512-cCmFDMSm26S6tQSDpBCg/NR8NENrVPhAJSf+XbxBG4rPFaaonlEoE9wHQmun+cls499TQGSb7ZyPBRlzgKfpeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/npm-normalize-package-bin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-4.0.0.tgz", + "integrity": "sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm-run-all2": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/npm-run-all2/-/npm-run-all2-8.0.4.tgz", + "integrity": "sha512-wdbB5My48XKp2ZfJUlhnLVihzeuA1hgBnqB2J9ahV77wLS+/YAJAlN8I+X3DIFIPZ3m5L7nplmlbhNiFDmXRDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "cross-spawn": "^7.0.6", + "memorystream": "^0.3.1", + "picomatch": "^4.0.2", + "pidtree": "^0.6.0", + "read-package-json-fast": "^4.0.0", + "shell-quote": "^1.7.3", + "which": "^5.0.0" + }, + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "npm-run-all2": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" + }, + "engines": { + "node": "^20.5.0 || >=22.0.0", + "npm": ">= 10" + } + }, + "node_modules/npm-run-all2/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/npm-run-all2/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16" + } + }, + "node_modules/npm-run-all2/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/npm-run-all2/node_modules/which": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm-run-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", + "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0", + "unicorn-magic": "^0.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", @@ -3336,29 +4525,27 @@ "url": "https://github.com/fb55/nth-check?sponsor=1" } }, - "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==", + "node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } + "license": "MIT" }, "node_modules/open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", + "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", "dev": true, "license": "MIT", "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "wsl-utils": "^0.1.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -3382,6 +4569,38 @@ "node": ">= 0.8.0" } }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -3395,6 +4614,19 @@ "node": ">=6" } }, + "node_modules/parse-ms": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", + "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/path-browserify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", @@ -3412,21 +4644,10 @@ "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" @@ -3436,7 +4657,6 @@ "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", @@ -3449,31 +4669,38 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, "node_modules/path-scurry/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/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } + "license": "MIT" }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true, + "license": "MIT" + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", "license": "MIT" }, "node_modules/picocolors": { @@ -3495,14 +4722,26 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "license": "MIT", + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/pinia": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.3.1.tgz", - "integrity": "sha512-khUlZSwt9xXCaTbbxFYBKDc/bWAGWJjOgvxETwkTN7KRm66EeT1ZdZj6i2ceh9sP2Pzqsbc704r2yngBrxBVug==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.3.tgz", + "integrity": "sha512-ttXO/InUULUXkMHpTdp9Fj4hLpD/2AoJdmAbAeW2yu1iy1k+pkFekQXw5VpC0/5p51IOR/jDaDRfRWRnMMsGOA==", "license": "MIT", "dependencies": { - "@vue/devtools-api": "^6.6.3", - "vue-demi": "^0.14.10" + "@vue/devtools-api": "^7.7.2" }, "funding": { "url": "https://github.com/sponsors/posva" @@ -3521,7 +4760,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", - "dev": true, "license": "MIT", "dependencies": { "@xmldom/xmldom": "^0.8.8", @@ -3584,11 +4822,26 @@ "node": ">= 0.8.0" } }, + "node_modules/pretty-ms": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.3.0.tgz", + "integrity": "sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parse-ms": "^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, "license": "MIT", "dependencies": { "kleur": "^3.0.3", @@ -3602,7 +4855,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -3639,11 +4891,24 @@ ], "license": "MIT" }, + "node_modules/read-package-json-fast": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-4.0.0.tgz", + "integrity": "sha512-qpt8EwugBWDw2cgE2W+/3oxC+KTez2uSVR8JU9Q36TXPAGCaozfQUs59v4j4GFpWTaw0i6hAZSvOmu1J0uOEUg==", + "dev": true, + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^4.0.0", + "npm-normalize-package-bin": "^4.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, "license": "MIT", "dependencies": { "inherits": "^2.0.3", @@ -3654,6 +4919,16 @@ "node": ">= 6" } }, + "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/reusify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", @@ -3665,11 +4940,16 @@ "node": ">=0.10.0" } }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "license": "MIT" + }, "node_modules/rimraf": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.4.1.tgz", "integrity": "sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==", - "dev": true, "license": "ISC", "dependencies": { "glob": "^9.2.0" @@ -3726,6 +5006,19 @@ "fsevents": "~2.3.2" } }, + "node_modules/run-applescript": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -3754,7 +5047,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, "funding": [ { "type": "github", @@ -3775,14 +5067,12 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/sax/-/sax-1.1.4.tgz", "integrity": "sha512-5f3k2PbGGp+YtKJjOItpg3P99IMD84E4HOvcfleTb5joCHNXYLsR9yWFPOYGgaeMPDubQILTCMdsFb2OMeOjtg==", - "dev": true, "license": "ISC" }, "node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true, + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -3795,7 +5085,6 @@ "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" @@ -3808,41 +5097,62 @@ "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/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "node_modules/shell-quote": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", "dev": true, - "license": "ISC" + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "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": "MIT" + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "node_modules/sirv": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", + "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==", "dev": true, "license": "MIT", + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, "engines": { - "node": ">=8" + "node": ">=18" } }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "license": "MIT" + }, "node_modules/slice-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -3856,18 +5166,6 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -3877,24 +5175,19 @@ "node": ">=0.10.0" } }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "node_modules/speakingurl": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", + "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" } }, "node_modules/split2": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", - "dev": true, "license": "ISC", "engines": { "node": ">= 10.x" @@ -3904,7 +5197,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" @@ -3914,7 +5206,6 @@ "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", @@ -3929,7 +5220,6 @@ "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" @@ -3938,6 +5228,19 @@ "node": ">=8" } }, + "node_modules/strip-final-newline": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", + "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -3951,6 +5254,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/superjson": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.2.tgz", + "integrity": "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==", + "license": "MIT", + "dependencies": { + "copy-anything": "^3.0.2" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -3968,7 +5283,6 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "dev": true, "license": "ISC", "dependencies": { "chownr": "^2.0.0", @@ -3986,57 +5300,72 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, "license": "ISC", "engines": { "node": ">=8" } }, - "node_modules/terser": { - "version": "5.44.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.0.tgz", - "integrity": "sha512-nIVck8DK+GM/0Frwd+nIhZ84pR/BX7rmXMfYwyg+Sri5oGVE99/E3KvXqpC2xHFxyqXyGHTKBSioxxplrO4I4w==", + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, + "node_modules/through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "license": "MIT", + "dependencies": { + "readable-stream": "3" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "dev": true, - "license": "BSD-2-Clause", - "optional": true, - "peer": true, + "license": "MIT", "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.15.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" + "fdir": "^6.5.0", + "picomatch": "^4.0.3" }, "engines": { - "node": ">=10" + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", - "optional": true, - "peer": true - }, - "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" + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } }, - "node_modules/through2": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "dependencies": { - "readable-stream": "3" + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/to-regex-range": { @@ -4045,34 +5374,43 @@ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=8.0" + "node": ">=6" } }, "node_modules/tree-kill": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true, "license": "MIT", "bin": { "tree-kill": "cli.js" } }, "node_modules/ts-api-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", - "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "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": ">=16" + "node": ">=18.12" }, "peerDependencies": { - "typescript": ">=4.2.0" + "typescript": ">=4.8.4" } }, "node_modules/tslib": { @@ -4094,23 +5432,10 @@ "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/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, "license": "Apache-2.0", "bin": { @@ -4121,33 +5446,128 @@ "node": ">=14.17" } }, + "node_modules/typescript-eslint": { + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.46.1.tgz", + "integrity": "sha512-VHgijW803JafdSsDO8I761r3SHrgk4T00IdyQ+/UsthtgPRsBWQLqoSxOolxTpxRKi1kGXK0bSz4CoAc9ObqJA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.46.1", + "@typescript-eslint/parser": "8.46.1", + "@typescript-eslint/typescript-estree": "8.46.1", + "@typescript-eslint/utils": "8.46.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, "node_modules/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/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, "license": "MIT", "engines": { "node": ">= 10.0.0" } }, + "node_modules/unplugin-utils": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/unplugin-utils/-/unplugin-utils-0.3.1.tgz", + "integrity": "sha512-5lWVjgi6vuHhJ526bI4nlCOmkCIF3nnfXkCMDeMJrtdvxTs6ZFCM8oNufGTsDbKv/tJ/xj8RpvXjRuPBZJuJog==", + "dev": true, + "license": "MIT", + "dependencies": { + "pathe": "^2.0.3", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/unplugin-utils/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/untildify": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -4162,25 +5582,27 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, "license": "MIT" }, "node_modules/vite": { - "version": "5.4.20", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.20.tgz", - "integrity": "sha512-j3lYzGC3P+B5Yfy/pfKNgVEg4+UtcIJcVRt2cDjIOmhLourAqPqf8P7acgxeiSgUB7E3p2P8/3gNIgDLpwzs4g==", + "version": "7.1.10", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.10.tgz", + "integrity": "sha512-CmuvUBzVJ/e3HGxhg6cYk88NGgTnBoOo7ogtfJJ0fefUWAxN/WDSUa50o+oVBxuIhO8FoEZW0j2eW7sfjs5EtA==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" + "esbuild": "^0.25.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": "^20.19.0 || >=22.12.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" @@ -4189,19 +5611,25 @@ "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" }, "peerDependenciesMeta": { "@types/node": { "optional": true }, + "jiti": { + "optional": true + }, "less": { "optional": true }, @@ -4222,113 +5650,264 @@ }, "terser": { "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true } } }, - "node_modules/vue": { - "version": "3.5.22", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.22.tgz", - "integrity": "sha512-toaZjQ3a/G/mYaLSbV+QsQhIdMo9x5rrqIpYRObsJ6T/J+RyCSFwN2LHNVH9v8uIcljDNa3QzPVdv3Y6b9hAJQ==", + "node_modules/vite-dev-rpc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vite-dev-rpc/-/vite-dev-rpc-1.1.0.tgz", + "integrity": "sha512-pKXZlgoXGoE8sEKiKJSng4hI1sQ4wi5YT24FCrwrLt6opmkjlqPPVmiPWWJn8M8byMxRGzp1CrFuqQs4M/Z39A==", + "dev": true, "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.22", - "@vue/compiler-sfc": "3.5.22", - "@vue/runtime-dom": "3.5.22", - "@vue/server-renderer": "3.5.22", - "@vue/shared": "3.5.22" + "birpc": "^2.4.0", + "vite-hot-client": "^2.1.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" }, "peerDependencies": { - "typescript": "*" + "vite": "^2.9.0 || ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.1 || ^7.0.0-0" + } + }, + "node_modules/vite-hot-client": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vite-hot-client/-/vite-hot-client-2.1.0.tgz", + "integrity": "sha512-7SpgZmU7R+dDnSmvXE1mfDtnHLHQSisdySVR7lO8ceAXvM0otZeuQQ6C8LrS5d/aYyP/QZ0hI0L+dIPrm4YlFQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "vite": "^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0" } }, - "node_modules/vue-demi": { - "version": "0.14.10", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", - "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", - "hasInstallScript": true, + "node_modules/vite-plugin-inspect": { + "version": "11.3.3", + "resolved": "https://registry.npmjs.org/vite-plugin-inspect/-/vite-plugin-inspect-11.3.3.tgz", + "integrity": "sha512-u2eV5La99oHoYPHE6UvbwgEqKKOQGz86wMg40CCosP6q8BkB6e5xPneZfYagK4ojPJSj5anHCrnvC20DpwVdRA==", + "dev": true, "license": "MIT", - "bin": { - "vue-demi-fix": "bin/vue-demi-fix.js", - "vue-demi-switch": "bin/vue-demi-switch.js" + "dependencies": { + "ansis": "^4.1.0", + "debug": "^4.4.1", + "error-stack-parser-es": "^1.0.5", + "ohash": "^2.0.11", + "open": "^10.2.0", + "perfect-debounce": "^2.0.0", + "sirv": "^3.0.1", + "unplugin-utils": "^0.3.0", + "vite-dev-rpc": "^1.1.0" }, "engines": { - "node": ">=12" + "node": ">=14" }, "funding": { "url": "https://github.com/sponsors/antfu" }, "peerDependencies": { - "@vue/composition-api": "^1.0.0-rc.1", - "vue": "^3.0.0-0 || ^2.6.0" + "vite": "^6.0.0 || ^7.0.0-0" }, "peerDependenciesMeta": { - "@vue/composition-api": { + "@nuxt/kit": { "optional": true } } }, - "node_modules/vue-eslint-parser": { - "version": "9.4.3", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz", - "integrity": "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==", + "node_modules/vite-plugin-inspect/node_modules/perfect-debounce": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.0.0.tgz", + "integrity": "sha512-fkEH/OBiKrqqI/yIgjR92lMfs2K8105zt/VT6+7eTjNwisrsh47CeIED9z58zI7DfKdH3uHAn25ziRZn3kgAow==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite-plugin-vue-devtools": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/vite-plugin-vue-devtools/-/vite-plugin-vue-devtools-8.0.2.tgz", + "integrity": "sha512-1069qvMBcyAu3yXQlvYrkwoyLOk0lSSR/gTKy/vy+Det7TXnouGei6ZcKwr5TIe938v/14oLlp0ow6FSJkkORA==", "dev": true, "license": "MIT", "dependencies": { - "debug": "^4.3.4", - "eslint-scope": "^7.1.1", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.1", - "esquery": "^1.4.0", - "lodash": "^4.17.21", - "semver": "^7.3.6" + "@vue/devtools-core": "^8.0.2", + "@vue/devtools-kit": "^8.0.2", + "@vue/devtools-shared": "^8.0.2", + "execa": "^9.6.0", + "sirv": "^3.0.2", + "vite-plugin-inspect": "^11.3.3", + "vite-plugin-vue-inspector": "^5.3.2" }, "engines": { - "node": "^14.17.0 || >=16.0.0" + "node": ">=v14.21.3" + }, + "peerDependencies": { + "vite": "^6.0.0 || ^7.0.0-0" + } + }, + "node_modules/vite-plugin-vue-devtools/node_modules/@vue/devtools-kit": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-8.0.2.tgz", + "integrity": "sha512-yjZKdEmhJzQqbOh4KFBfTOQjDPMrjjBNCnHBvnTGJX+YLAqoUtY2J+cg7BE+EA8KUv8LprECq04ts75wCoIGWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^8.0.2", + "birpc": "^2.5.0", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^2.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.2" + } + }, + "node_modules/vite-plugin-vue-devtools/node_modules/@vue/devtools-shared": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-8.0.2.tgz", + "integrity": "sha512-mLU0QVdy5Lp40PMGSixDw/Kbd6v5dkQXltd2r+mdVQV7iUog2NlZuLxFZApFZ/mObUBDhoCpf0T3zF2FWWdeHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "rfdc": "^1.4.1" + } + }, + "node_modules/vite-plugin-vue-devtools/node_modules/perfect-debounce": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.0.0.tgz", + "integrity": "sha512-fkEH/OBiKrqqI/yIgjR92lMfs2K8105zt/VT6+7eTjNwisrsh47CeIED9z58zI7DfKdH3uHAn25ziRZn3kgAow==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite-plugin-vue-inspector": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/vite-plugin-vue-inspector/-/vite-plugin-vue-inspector-5.3.2.tgz", + "integrity": "sha512-YvEKooQcSiBTAs0DoYLfefNja9bLgkFM7NI2b07bE2SruuvX0MEa9cMaxjKVMkeCp5Nz9FRIdcN1rOdFVBeL6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.23.0", + "@babel/plugin-proposal-decorators": "^7.23.0", + "@babel/plugin-syntax-import-attributes": "^7.22.5", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-transform-typescript": "^7.22.15", + "@vue/babel-plugin-jsx": "^1.1.5", + "@vue/compiler-dom": "^3.3.4", + "kolorist": "^1.8.0", + "magic-string": "^0.30.4" + }, + "peerDependencies": { + "vite": "^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0" + } + }, + "node_modules/vite/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/vite/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/mysticatea" + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vscode-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/vue": { + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.22.tgz", + "integrity": "sha512-toaZjQ3a/G/mYaLSbV+QsQhIdMo9x5rrqIpYRObsJ6T/J+RyCSFwN2LHNVH9v8uIcljDNa3QzPVdv3Y6b9hAJQ==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.22", + "@vue/compiler-sfc": "3.5.22", + "@vue/runtime-dom": "3.5.22", + "@vue/server-renderer": "3.5.22", + "@vue/shared": "3.5.22" }, "peerDependencies": { - "eslint": ">=6.0.0" + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/vue-eslint-parser/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==", + "node_modules/vue-eslint-parser": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-10.2.0.tgz", + "integrity": "sha512-CydUvFOQKD928UzZhTp4pr2vWz1L+H99t7Pkln2QSPdvmURT0MoC4wUccfCnuEaihNsu9aYYyk+bep8rlfkUXw==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "debug": "^4.4.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.6.0", + "semver": "^7.6.3" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" } }, - "node_modules/vue-eslint-parser/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "node_modules/vue-eslint-parser/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": "BSD-2-Clause", + "license": "Apache-2.0", "engines": { - "node": ">=4.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/vue-facing-decorator": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/vue-facing-decorator/-/vue-facing-decorator-3.0.4.tgz", - "integrity": "sha512-Lk90PevJllB6qRRdLvLFjATZrv00nof1Ob6afavKL7Pc7V3eEin3vhdvEDRORdWKVvNoXhJbHejngWVuT0Pt0g==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/vue-facing-decorator/-/vue-facing-decorator-4.0.1.tgz", + "integrity": "sha512-zBvPoiXVVCOSctoKmcYUHFu2qu0AGYAZOfT6LnPqcrSSOpElTJTd21cOIrGrnA1rYwzlp8jhQLmlcBKv1ETNRA==", "license": "MIT", + "dependencies": { + "facing-metadata": "^2.0.0" + }, "peerDependencies": { "vue": "^3.0.0" } @@ -4348,40 +5927,33 @@ "vue": "^3.5.0" } }, - "node_modules/vue-template-compiler": { - "version": "2.7.16", - "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz", - "integrity": "sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "de-indent": "^1.0.2", - "he": "^1.2.0" - } + "node_modules/vue-router/node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "license": "MIT" }, "node_modules/vue-tsc": { - "version": "1.8.27", - "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-1.8.27.tgz", - "integrity": "sha512-WesKCAZCRAbmmhuGl3+VrdWItEvfoFIPXOvUJkjULi+x+6G/Dy69yO3TBRJDr9eUlmsNAwVmxsNZxvHKzbkKdg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-3.1.1.tgz", + "integrity": "sha512-fyixKxFniOVgn+L/4+g8zCG6dflLLt01Agz9jl3TO45Bgk87NZJRmJVPsiK+ouq3LB91jJCbOV+pDkzYTxbI7A==", "dev": true, "license": "MIT", "dependencies": { - "@volar/typescript": "~1.11.1", - "@vue/language-core": "1.8.27", - "semver": "^7.5.4" + "@volar/typescript": "2.4.23", + "@vue/language-core": "3.1.1" }, "bin": { "vue-tsc": "bin/vue-tsc.js" }, "peerDependencies": { - "typescript": "*" + "typescript": ">=5.0.0" } }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -4407,7 +5979,6 @@ "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", @@ -4421,12 +5992,21 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "node_modules/wsl-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", + "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", "dev": true, - "license": "ISC" + "license": "MIT", + "dependencies": { + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/xml-name-validator": { "version": "4.0.0", @@ -4442,7 +6022,6 @@ "version": "0.5.0", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", - "dev": true, "license": "MIT", "dependencies": { "sax": ">=0.6.0", @@ -4456,7 +6035,6 @@ "version": "11.0.1", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "dev": true, "license": "MIT", "engines": { "node": ">=4.0" @@ -4466,16 +6044,15 @@ "version": "15.1.1", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", - "dev": true, "license": "MIT", "engines": { "node": ">=8.0" } }, "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true, "license": "ISC" }, @@ -4483,7 +6060,6 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, "license": "MIT", "dependencies": { "buffer-crc32": "~0.2.3", @@ -4502,6 +6078,19 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/yoctocolors": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz", + "integrity": "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/test-apps/daily-notification-test/package.json b/test-apps/daily-notification-test/package.json new file mode 100644 index 0000000..f992939 --- /dev/null +++ b/test-apps/daily-notification-test/package.json @@ -0,0 +1,42 @@ +{ + "name": "daily-notification-test", + "version": "0.0.0", + "private": true, + "type": "module", + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "build-only": "vite build", + "type-check": "vue-tsc --build", + "lint": "eslint . --fix" + }, + "dependencies": { + "@capacitor/android": "^6.2.1", + "@capacitor/cli": "^6.2.1", + "@capacitor/core": "^6.2.1", + "date-fns": "^4.1.0", + "pinia": "^3.0.3", + "vue": "^3.5.22", + "vue-facing-decorator": "^4.0.1", + "vue-router": "^4.5.1" + }, + "devDependencies": { + "@tsconfig/node22": "^22.0.2", + "@types/node": "^22.18.6", + "@vitejs/plugin-vue": "^6.0.1", + "@vue/eslint-config-typescript": "^14.6.0", + "@vue/tsconfig": "^0.8.1", + "eslint": "^9.33.0", + "eslint-plugin-vue": "~10.4.0", + "jiti": "^2.5.1", + "npm-run-all2": "^8.0.4", + "typescript": "~5.9.0", + "vite": "^7.1.7", + "vite-plugin-vue-devtools": "^8.0.2", + "vue-tsc": "^3.1.0" + } +} diff --git a/test-apps/daily-notification-test/public/favicon.ico b/test-apps/daily-notification-test/public/favicon.ico new file mode 100644 index 0000000..df36fcf Binary files /dev/null and b/test-apps/daily-notification-test/public/favicon.ico differ diff --git a/test-apps/daily-notification-test/src/App.vue b/test-apps/daily-notification-test/src/App.vue new file mode 100644 index 0000000..8c1536b --- /dev/null +++ b/test-apps/daily-notification-test/src/App.vue @@ -0,0 +1,125 @@ + + + + + + + \ No newline at end of file diff --git a/test-apps/daily-notification-test/src/assets/base.css b/test-apps/daily-notification-test/src/assets/base.css new file mode 100644 index 0000000..8816868 --- /dev/null +++ b/test-apps/daily-notification-test/src/assets/base.css @@ -0,0 +1,86 @@ +/* color palette from */ +:root { + --vt-c-white: #ffffff; + --vt-c-white-soft: #f8f8f8; + --vt-c-white-mute: #f2f2f2; + + --vt-c-black: #181818; + --vt-c-black-soft: #222222; + --vt-c-black-mute: #282828; + + --vt-c-indigo: #2c3e50; + + --vt-c-divider-light-1: rgba(60, 60, 60, 0.29); + --vt-c-divider-light-2: rgba(60, 60, 60, 0.12); + --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65); + --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48); + + --vt-c-text-light-1: var(--vt-c-indigo); + --vt-c-text-light-2: rgba(60, 60, 60, 0.66); + --vt-c-text-dark-1: var(--vt-c-white); + --vt-c-text-dark-2: rgba(235, 235, 235, 0.64); +} + +/* semantic color variables for this project */ +:root { + --color-background: var(--vt-c-white); + --color-background-soft: var(--vt-c-white-soft); + --color-background-mute: var(--vt-c-white-mute); + + --color-border: var(--vt-c-divider-light-2); + --color-border-hover: var(--vt-c-divider-light-1); + + --color-heading: var(--vt-c-text-light-1); + --color-text: var(--vt-c-text-light-1); + + --section-gap: 160px; +} + +@media (prefers-color-scheme: dark) { + :root { + --color-background: var(--vt-c-black); + --color-background-soft: var(--vt-c-black-soft); + --color-background-mute: var(--vt-c-black-mute); + + --color-border: var(--vt-c-divider-dark-2); + --color-border-hover: var(--vt-c-divider-dark-1); + + --color-heading: var(--vt-c-text-dark-1); + --color-text: var(--vt-c-text-dark-2); + } +} + +*, +*::before, +*::after { + box-sizing: border-box; + margin: 0; + font-weight: normal; +} + +body { + min-height: 100vh; + color: var(--color-text); + background: var(--color-background); + transition: + color 0.5s, + background-color 0.5s; + line-height: 1.6; + font-family: + Inter, + -apple-system, + BlinkMacSystemFont, + 'Segoe UI', + Roboto, + Oxygen, + Ubuntu, + Cantarell, + 'Fira Sans', + 'Droid Sans', + 'Helvetica Neue', + sans-serif; + font-size: 15px; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} diff --git a/test-apps/daily-notification-test/src/assets/logo.svg b/test-apps/daily-notification-test/src/assets/logo.svg new file mode 100644 index 0000000..7565660 --- /dev/null +++ b/test-apps/daily-notification-test/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/test-apps/daily-notification-test/src/assets/main.css b/test-apps/daily-notification-test/src/assets/main.css new file mode 100644 index 0000000..36fb845 --- /dev/null +++ b/test-apps/daily-notification-test/src/assets/main.css @@ -0,0 +1,35 @@ +@import './base.css'; + +#app { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + font-weight: normal; +} + +a, +.green { + text-decoration: none; + color: hsla(160, 100%, 37%, 1); + transition: 0.4s; + padding: 3px; +} + +@media (hover: hover) { + a:hover { + background-color: hsla(160, 100%, 37%, 0.2); + } +} + +@media (min-width: 1024px) { + body { + display: flex; + place-items: center; + } + + #app { + display: grid; + grid-template-columns: 1fr 1fr; + padding: 0 2rem; + } +} diff --git a/test-apps/daily-notification-test/src/components/HelloWorld.vue b/test-apps/daily-notification-test/src/components/HelloWorld.vue new file mode 100644 index 0000000..d174cf8 --- /dev/null +++ b/test-apps/daily-notification-test/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/test-apps/daily-notification-test/src/components/TheWelcome.vue b/test-apps/daily-notification-test/src/components/TheWelcome.vue new file mode 100644 index 0000000..6092dff --- /dev/null +++ b/test-apps/daily-notification-test/src/components/TheWelcome.vue @@ -0,0 +1,94 @@ + + + diff --git a/test-apps/daily-notification-test/src/components/WelcomeItem.vue b/test-apps/daily-notification-test/src/components/WelcomeItem.vue new file mode 100644 index 0000000..6d7086a --- /dev/null +++ b/test-apps/daily-notification-test/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/test-apps/daily-notification-test/src/components/cards/ActionCard.vue b/test-apps/daily-notification-test/src/components/cards/ActionCard.vue new file mode 100644 index 0000000..adaa885 --- /dev/null +++ b/test-apps/daily-notification-test/src/components/cards/ActionCard.vue @@ -0,0 +1,141 @@ + + + + + + + diff --git a/test-apps/daily-notification-test/src/components/cards/StatusCard.vue b/test-apps/daily-notification-test/src/components/cards/StatusCard.vue new file mode 100644 index 0000000..9388a3a --- /dev/null +++ b/test-apps/daily-notification-test/src/components/cards/StatusCard.vue @@ -0,0 +1,202 @@ + + + + + + + diff --git a/test-apps/daily-notification-test/src/components/icons/IconCommunity.vue b/test-apps/daily-notification-test/src/components/icons/IconCommunity.vue new file mode 100644 index 0000000..2dc8b05 --- /dev/null +++ b/test-apps/daily-notification-test/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/test-apps/daily-notification-test/src/components/icons/IconDocumentation.vue b/test-apps/daily-notification-test/src/components/icons/IconDocumentation.vue new file mode 100644 index 0000000..6d4791c --- /dev/null +++ b/test-apps/daily-notification-test/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/test-apps/daily-notification-test/src/components/icons/IconEcosystem.vue b/test-apps/daily-notification-test/src/components/icons/IconEcosystem.vue new file mode 100644 index 0000000..c3a4f07 --- /dev/null +++ b/test-apps/daily-notification-test/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/test-apps/daily-notification-test/src/components/icons/IconSupport.vue b/test-apps/daily-notification-test/src/components/icons/IconSupport.vue new file mode 100644 index 0000000..7452834 --- /dev/null +++ b/test-apps/daily-notification-test/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/test-apps/daily-notification-test/src/components/icons/IconTooling.vue b/test-apps/daily-notification-test/src/components/icons/IconTooling.vue new file mode 100644 index 0000000..660598d --- /dev/null +++ b/test-apps/daily-notification-test/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/test-apps/daily-notification-test/src/components/layout/AppFooter.vue b/test-apps/daily-notification-test/src/components/layout/AppFooter.vue new file mode 100644 index 0000000..2354d89 --- /dev/null +++ b/test-apps/daily-notification-test/src/components/layout/AppFooter.vue @@ -0,0 +1,113 @@ + + + + + + + diff --git a/test-apps/daily-notification-test/src/components/layout/AppHeader.vue b/test-apps/daily-notification-test/src/components/layout/AppHeader.vue new file mode 100644 index 0000000..2f5d1f7 --- /dev/null +++ b/test-apps/daily-notification-test/src/components/layout/AppHeader.vue @@ -0,0 +1,270 @@ + + + + + + + diff --git a/test-apps/android-test/src/components/ui/ErrorDialog.vue b/test-apps/daily-notification-test/src/components/ui/ErrorDialog.vue similarity index 54% rename from test-apps/android-test/src/components/ui/ErrorDialog.vue rename to test-apps/daily-notification-test/src/components/ui/ErrorDialog.vue index b153e11..0375d43 100644 --- a/test-apps/android-test/src/components/ui/ErrorDialog.vue +++ b/test-apps/daily-notification-test/src/components/ui/ErrorDialog.vue @@ -1,8 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/test-apps/daily-notification-test/src/views/LogsView.vue b/test-apps/daily-notification-test/src/views/LogsView.vue new file mode 100644 index 0000000..17437e6 --- /dev/null +++ b/test-apps/daily-notification-test/src/views/LogsView.vue @@ -0,0 +1,475 @@ + + + + + + + diff --git a/test-apps/daily-notification-test/src/views/NotFoundView.vue b/test-apps/daily-notification-test/src/views/NotFoundView.vue new file mode 100644 index 0000000..ed6d6cb --- /dev/null +++ b/test-apps/daily-notification-test/src/views/NotFoundView.vue @@ -0,0 +1,70 @@ + + + + + diff --git a/test-apps/daily-notification-test/src/views/NotificationsView.vue b/test-apps/daily-notification-test/src/views/NotificationsView.vue new file mode 100644 index 0000000..e98238f --- /dev/null +++ b/test-apps/daily-notification-test/src/views/NotificationsView.vue @@ -0,0 +1,54 @@ + + + + + diff --git a/test-apps/daily-notification-test/src/views/ScheduleView.vue b/test-apps/daily-notification-test/src/views/ScheduleView.vue new file mode 100644 index 0000000..7ba05e2 --- /dev/null +++ b/test-apps/daily-notification-test/src/views/ScheduleView.vue @@ -0,0 +1,180 @@ + + + + + + + diff --git a/test-apps/android-test/src/views/SettingsView.vue b/test-apps/daily-notification-test/src/views/SettingsView.vue similarity index 62% rename from test-apps/android-test/src/views/SettingsView.vue rename to test-apps/daily-notification-test/src/views/SettingsView.vue index 65dd793..5c1741f 100644 --- a/test-apps/android-test/src/views/SettingsView.vue +++ b/test-apps/daily-notification-test/src/views/SettingsView.vue @@ -1,21 +1,11 @@ - - @@ -29,43 +19,36 @@ export default class SettingsView extends Vue {} diff --git a/test-apps/daily-notification-test/src/views/StatusView.vue b/test-apps/daily-notification-test/src/views/StatusView.vue new file mode 100644 index 0000000..1dfeca4 --- /dev/null +++ b/test-apps/daily-notification-test/src/views/StatusView.vue @@ -0,0 +1,54 @@ + + + + + diff --git a/test-apps/daily-notification-test/tsconfig.app.json b/test-apps/daily-notification-test/tsconfig.app.json new file mode 100644 index 0000000..cbd2fbc --- /dev/null +++ b/test-apps/daily-notification-test/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "useDefineForClassFields": false, + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/test-apps/daily-notification-test/tsconfig.json b/test-apps/daily-notification-test/tsconfig.json new file mode 100644 index 0000000..66b5e57 --- /dev/null +++ b/test-apps/daily-notification-test/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/test-apps/daily-notification-test/tsconfig.node.json b/test-apps/daily-notification-test/tsconfig.node.json new file mode 100644 index 0000000..a83dfc9 --- /dev/null +++ b/test-apps/daily-notification-test/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node22/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*", + "eslint.config.*" + ], + "compilerOptions": { + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/test-apps/daily-notification-test/vite.config.ts b/test-apps/daily-notification-test/vite.config.ts new file mode 100644 index 0000000..4217010 --- /dev/null +++ b/test-apps/daily-notification-test/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueDevTools from 'vite-plugin-vue-devtools' + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueDevTools(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + }, + }, +}) diff --git a/test-apps/electron-test/.gitignore b/test-apps/electron-test/.gitignore deleted file mode 100644 index b84c901..0000000 --- a/test-apps/electron-test/.gitignore +++ /dev/null @@ -1,114 +0,0 @@ -# Dependencies -node_modules/ -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# Build outputs -dist/ -build/ -*.tsbuildinfo - -# Electron -out/ -app/ -packages/ - -# IDE and editor files -.vscode/ -.idea/ -*.swp -*.swo -*~ - -# OS generated files -.DS_Store -.DS_Store? -._* -.Spotlight-V100 -.Trashes -ehthumbs.db -Thumbs.db - -# Logs -logs -*.log - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Coverage directory used by tools like istanbul -coverage/ -*.lcov - -# nyc test coverage -.nyc_output - -# Dependency directories -jspm_packages/ - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Microbundle cache -.rpt2_cache/ -.rts2_cache_cjs/ -.rts2_cache_es/ -.rts2_cache_umd/ - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -.env -.env.test -.env.local -.env.development.local -.env.test.local -.env.production.local - -# parcel-bundler cache (https://parceljs.org/) -.cache -.parcel-cache - -# next.js build output -.next - -# nuxt.js build output -.nuxt - -# vuepress build output -.vuepress/dist - -# Serverless directories -.serverless/ - -# FuseBox cache -.fusebox/ - -# DynamoDB Local files -.dynamodb/ - -# TernJS port file -.tern-port - -# Electron specific -*.app -*.dmg -*.exe -*.deb -*.rpm -*.AppImage -*.snap diff --git a/test-apps/electron-test/main.js b/test-apps/electron-test/main.js deleted file mode 100644 index 145dace..0000000 --- a/test-apps/electron-test/main.js +++ /dev/null @@ -1,117 +0,0 @@ -const { app, BrowserWindow, ipcMain } = require('electron'); -const path = require('path'); - -// Mock plugin for Electron development -const DailyNotification = { - async configure(options) { - console.log('Electron Configure called:', options); - return Promise.resolve(); - }, - async scheduleDailyNotification(options) { - console.log('Electron Schedule called:', options); - return Promise.resolve(); - }, - async getDebugInfo() { - return Promise.resolve({ - status: 'Electron Mock Mode', - configuration: { - storage: 'mock', - platform: 'electron', - version: '1.0.0' - }, - recentErrors: [], - performance: { - overallScore: 95, - memoryUsage: 15.2, - cpuUsage: 1.2 - } - }); - }, - async getPerformanceMetrics() { - return Promise.resolve({ - overallScore: 95, - databasePerformance: 100, - memoryEfficiency: 95, - batteryEfficiency: 100, - objectPoolEfficiency: 100, - totalDatabaseQueries: 0, - averageMemoryUsage: 15.2, - objectPoolHits: 0, - backgroundCpuUsage: 0.5, - totalNetworkRequests: 0, - recommendations: ['Electron mock mode - no optimizations needed'] - }); - } -}; - -// IPC handlers for Electron -ipcMain.handle('configure-plugin', async (event, options) => { - try { - await DailyNotification.configure(options); - return { success: true, message: 'Configuration successful' }; - } catch (error) { - return { success: false, error: error.message }; - } -}); - -ipcMain.handle('schedule-notification', async (event, options) => { - try { - await DailyNotification.scheduleDailyNotification(options); - return { success: true, message: 'Notification scheduled' }; - } catch (error) { - return { success: false, error: error.message }; - } -}); - -ipcMain.handle('get-debug-info', async () => { - try { - const info = await DailyNotification.getDebugInfo(); - return { success: true, data: info }; - } catch (error) { - return { success: false, error: error.message }; - } -}); - -ipcMain.handle('get-performance-metrics', async () => { - try { - const metrics = await DailyNotification.getPerformanceMetrics(); - return { success: true, data: metrics }; - } catch (error) { - return { success: false, error: error.message }; - } -}); - -function createWindow() { - const mainWindow = new BrowserWindow({ - width: 800, - height: 600, - webPreferences: { - nodeIntegration: false, - contextIsolation: true, - preload: path.join(__dirname, 'preload.js') - }, - title: 'Daily Notification - Electron Test' - }); - - // Load the web app - mainWindow.loadFile('dist/index.html'); - - // Open DevTools in development - if (process.argv.includes('--dev')) { - mainWindow.webContents.openDevTools(); - } -} - -app.whenReady().then(createWindow); - -app.on('window-all-closed', () => { - if (process.platform !== 'darwin') { - app.quit(); - } -}); - -app.on('activate', () => { - if (BrowserWindow.getAllWindows().length === 0) { - createWindow(); - } -}); diff --git a/test-apps/electron-test/package.json b/test-apps/electron-test/package.json deleted file mode 100644 index d38b31b..0000000 --- a/test-apps/electron-test/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "daily-notification-electron-test", - "version": "1.0.0", - "description": "Minimal Electron test app for Daily Notification Plugin", - "main": "main.js", - "scripts": { - "start": "electron .", - "dev": "electron . --dev", - "build": "webpack --mode=production", - "build-web": "webpack --mode=production", - "electron": "npm run build-web && electron ." - }, - "keywords": ["capacitor", "electron", "notifications", "test"], - "author": "Matthew Raymer", - "license": "MIT", - "dependencies": { - "@capacitor/core": "^5.0.0", - "@capacitor/cli": "^5.0.0", - "electron": "^25.0.0" - }, - "devDependencies": { - "webpack": "^5.88.0", - "webpack-cli": "^5.1.0", - "html-webpack-plugin": "^5.5.0", - "typescript": "^5.0.0", - "ts-loader": "^9.4.0" - } -} diff --git a/test-apps/electron-test/preload.js b/test-apps/electron-test/preload.js deleted file mode 100644 index aacb6cc..0000000 --- a/test-apps/electron-test/preload.js +++ /dev/null @@ -1,10 +0,0 @@ -const { contextBridge, ipcRenderer } = require('electron'); - -// Expose protected methods that allow the renderer process to use -// the ipcRenderer without exposing the entire object -contextBridge.exposeInMainWorld('electronAPI', { - configurePlugin: (options) => ipcRenderer.invoke('configure-plugin', options), - scheduleNotification: (options) => ipcRenderer.invoke('schedule-notification', options), - getDebugInfo: () => ipcRenderer.invoke('get-debug-info'), - getPerformanceMetrics: () => ipcRenderer.invoke('get-performance-metrics') -}); diff --git a/test-apps/electron-test/src/index.html b/test-apps/electron-test/src/index.html deleted file mode 100644 index 605eb44..0000000 --- a/test-apps/electron-test/src/index.html +++ /dev/null @@ -1,476 +0,0 @@ - - - - - - Daily Notification - Electron Test - - - -
-

⚡ TimeSafari Daily Notification - Electron Test

- -
Ready
- - -
-

🔐 Permission Management

-
-
- - - -
-
- - -
-

⚙️ Configuration

-
-
- - -
-
- - -
-

📊 Status Monitoring

-
-
- - -
-
- - -
-

⚡ Electron-Specific Features

-
-
- - - -
-
- - -
-

🧪 Testing & Debug

-
- - - - -
-
- - -
-

🚀 Phase 4: TimeSafari Components

-
- - - - -
-
- - -
-

⏰ Static Daily Reminders

-
- - - - -
-
-

Reminder Configuration

-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- -
-
-
- - -
-

⚠️ Error Handling

-
-
- - -
-

📝 Activity Log

-
- -
-
- - -
- - - - diff --git a/test-apps/electron-test/src/index.ts b/test-apps/electron-test/src/index.ts deleted file mode 100644 index 9ea4372..0000000 --- a/test-apps/electron-test/src/index.ts +++ /dev/null @@ -1,1085 +0,0 @@ -import { ConfigLoader, MockDailyNotificationService, TestLogger } from '../shared/config-loader'; - -// Phase 4: Import TimeSafari components -import { EndorserAPIClient } from '../shared/typescript/EndorserAPIClient'; -import { SecurityManager } from '../shared/typescript/SecurityManager'; -import { TimeSafariNotificationManager } from '../shared/typescript/TimeSafariNotificationManager'; -// import { -// TimeSafariUser, -// TimeSafariPreferences, -// EnhancedTimeSafariNotification, -// TimeSafariNotificationType -// } from '../../../src/definitions'; - -// Enhanced UI components for Electron testing -class PermissionManager { - private container: HTMLElement; - private dialogContainer: HTMLElement; - - constructor(container: HTMLElement, dialogContainer: HTMLElement) { - this.container = container; - this.dialogContainer = dialogContainer; - } - - async updateStatus(): Promise { - // Mock permission status for Electron testing - const mockStatus = { - granted: true, - notifications: 'granted' as const, - serviceWorker: 'active' as const - }; - - this.renderStatus(mockStatus); - } - - private renderStatus(status: Record): void { - const statusClass = status.granted ? 'status-granted' : 'status-denied'; - const statusText = status.granted ? 'Granted' : 'Denied'; - - this.container.innerHTML = ` -
-
- ${status.granted ? '✓' : '✗'} - ${statusText} -
-
-
- Notifications: - - ${status.notifications} - -
-
- Service Worker: - - ${status.serviceWorker} - -
-
-
- `; - } - - showPermissionDialog(): void { - const dialog = document.createElement('div'); - dialog.className = 'dialog-overlay'; - dialog.innerHTML = ` -
-

Enable Daily Notifications

-

Get notified about new offers, projects, people, and items in your TimeSafari community.

-
    -
  • New offers directed to you
  • -
  • Changes to your projects
  • -
  • Updates from favorited people
  • -
  • New items of interest
  • -
-
- - - -
-
- `; - - this.dialogContainer.appendChild(dialog); - - dialog.querySelector('#allow-permissions')?.addEventListener('click', () => { - this.hideDialog(); - this.updateStatus(); - }); - - dialog.querySelector('#deny-permissions')?.addEventListener('click', () => { - this.hideDialog(); - }); - - dialog.querySelector('#never-permissions')?.addEventListener('click', () => { - this.hideDialog(); - }); - } - - private hideDialog(): void { - const dialog = this.dialogContainer.querySelector('.dialog-overlay'); - if (dialog) { - dialog.remove(); - } - } -} - -class SettingsPanel { - private container: HTMLElement; - - constructor(container: HTMLElement) { - this.container = container; - } - - render(): void { - this.container.innerHTML = ` -
-
- -
- -
- - -
- -
- -
- - - - -
-
- -
- -
- - - -
-
- -
- -
-
- `; - } -} - -class StatusDashboard { - private container: HTMLElement; - - constructor(container: HTMLElement) { - this.container = container; - } - - render(): void { - this.container.innerHTML = ` -
-
-
-
Overall Status
-
Active
-
- -
-
Next Notification
-
2h 15m
-
- -
-
Last Outcome
-
Success
-
- -
-
Cache Age
-
1h 23m
-
-
- -
-

Performance

-
-
- Success Rate: - 95% -
-
- Error Count: - 2 -
-
-
-
- `; - } -} - -class ErrorDisplay { - private container: HTMLElement; - - constructor(container: HTMLElement) { - this.container = container; - } - - showError(error: Error): void { - this.container.innerHTML = ` -
-
⚠️
-
-

Something went wrong

-

${error.message}

-

Error Code: ${error.name}

-
-
- - -
-
- `; - } - - hide(): void { - this.container.innerHTML = ''; - } -} - -// Enhanced test interface for TimeSafari Electron integration -// Enhanced test interface for TimeSafari Electron integration with Phase 4 components -class TimeSafariElectronTestApp { - private statusElement: HTMLElement; - private logElement: HTMLElement; - private configLoader: ConfigLoader; - private notificationService: MockDailyNotificationService; - private logger: TestLogger; - - // Phase 4: TimeSafari components - private endorserAPIClient: EndorserAPIClient; - private securityManager: SecurityManager; - private timeSafariNotificationManager: TimeSafariNotificationManager; - - // UI Components - private permissionManager: PermissionManager; - private settingsPanel: SettingsPanel; - private statusDashboard: StatusDashboard; - private errorDisplay: ErrorDisplay; - - constructor() { - const statusElement = document.getElementById('status'); - const logElement = document.getElementById('log'); - if (!statusElement || !logElement) { - throw new Error('Required DOM elements not found'); - } - this.statusElement = statusElement; - this.logElement = logElement; - this.configLoader = ConfigLoader.getInstance(); - this.logger = new TestLogger('debug'); - this.notificationService = new MockDailyNotificationService(this.configLoader.getConfig()); - - // Phase 4: Initialize TimeSafari components - this.endorserAPIClient = new EndorserAPIClient(this.configLoader.getEndorserAPIConfig()); - this.securityManager = new SecurityManager(this.configLoader.getSecurityConfig()); - this.timeSafariNotificationManager = new TimeSafariNotificationManager(); - - // Initialize UI components - const permissionStatusContainer = document.getElementById('permission-status-container'); - const permissionDialogContainer = document.getElementById('permission-dialog-container'); - const settingsContainer = document.getElementById('settings-container'); - const statusContainer = document.getElementById('status-container'); - const errorContainer = document.getElementById('error-container'); - - if (!permissionStatusContainer || !permissionDialogContainer || !settingsContainer || !statusContainer || !errorContainer) { - throw new Error('Required UI containers not found'); - } - - this.permissionManager = new PermissionManager( - permissionStatusContainer, - permissionDialogContainer - ); - this.settingsPanel = new SettingsPanel(settingsContainer); - this.statusDashboard = new StatusDashboard(statusContainer); - this.errorDisplay = new ErrorDisplay(errorContainer); - - this.setupEventListeners(); - this.initializeUI(); - this.initializePhase4Components(); - this.log('TimeSafari Electron Test app initialized with Phase 4 components'); - } - - private setupEventListeners(): void { - // Original test functionality - document.getElementById('configure')?.addEventListener('click', () => this.testConfigure()); - document.getElementById('schedule')?.addEventListener('click', () => this.testSchedule()); - document.getElementById('endorser-api')?.addEventListener('click', () => this.testEndorserAPI()); - document.getElementById('callbacks')?.addEventListener('click', () => this.testCallbacks()); - document.getElementById('debug-info')?.addEventListener('click', () => this.testDebugInfo()); - document.getElementById('performance')?.addEventListener('click', () => this.testPerformance()); - document.getElementById('clear-log')?.addEventListener('click', () => this.clearLog()); - - // Enhanced UI functionality - document.getElementById('check-permissions')?.addEventListener('click', () => this.checkPermissions()); - document.getElementById('request-permissions')?.addEventListener('click', () => this.requestPermissions()); - document.getElementById('open-settings')?.addEventListener('click', () => this.openSettings()); - document.getElementById('test-notification')?.addEventListener('click', () => this.testNotification()); - document.getElementById('check-status')?.addEventListener('click', () => this.testStatus()); - document.getElementById('refresh-status')?.addEventListener('click', () => this.refreshStatus()); - document.getElementById('service-worker-status')?.addEventListener('click', () => this.checkServiceWorker()); - document.getElementById('push-notification-status')?.addEventListener('click', () => this.checkPushNotifications()); - - // Phase 4: TimeSafari component testing - document.getElementById('test-security-manager')?.addEventListener('click', () => this.testSecurityManager()); - document.getElementById('test-endorser-api-client')?.addEventListener('click', () => this.testEndorserAPIClient()); - document.getElementById('test-notification-manager')?.addEventListener('click', () => this.testTimeSafariNotificationManager()); - document.getElementById('test-phase4-integration')?.addEventListener('click', () => this.testPhase4Integration()); - - // Static Daily Reminder event listeners - document.getElementById('schedule-reminder')?.addEventListener('click', () => this.scheduleDailyReminder()); - document.getElementById('cancel-reminder')?.addEventListener('click', () => this.cancelDailyReminder()); - document.getElementById('get-reminders')?.addEventListener('click', () => this.getScheduledReminders()); - document.getElementById('update-reminder')?.addEventListener('click', () => this.updateDailyReminder()); - } - - private async initializeUI(): Promise { - try { - // Initialize UI components - await this.permissionManager.updateStatus(); - this.settingsPanel.render(); - this.statusDashboard.render(); - - this.log('✅ Enhanced UI components initialized'); - } catch (error) { - this.log(`❌ UI initialization failed: ${error}`); - this.errorDisplay.showError(error as Error); - } - } - - // Phase 4: Initialize TimeSafari components - private async initializePhase4Components(): Promise { - try { - this.log('Initializing Phase 4 TimeSafari components...'); - - // Initialize SecurityManager with test DID - const timeSafariUser = this.configLoader.getTimeSafariUser(); - const securityInitialized = await this.securityManager.initialize(timeSafariUser.activeDid); - - if (securityInitialized) { - this.log('✅ SecurityManager initialized successfully'); - - // Generate JWT token for API authentication - const jwt = await this.securityManager.generateJWT({ - scope: 'notifications', - audience: 'endorser-api' - }); - - if (jwt) { - this.endorserAPIClient.setAuthToken(jwt); - this.log('✅ JWT token generated and set for EndorserAPI'); - } - } else { - this.log('❌ SecurityManager initialization failed'); - } - - // Initialize TimeSafariNotificationManager - const managerInitialized = await this.timeSafariNotificationManager.initialize(timeSafariUser); - - if (managerInitialized) { - this.log('✅ TimeSafariNotificationManager initialized successfully'); - } else { - this.log('❌ TimeSafariNotificationManager initialization failed'); - } - - this.log('Phase 4 components initialization completed'); - - } catch (error) { - this.log('Error initializing Phase 4 components:', error); - this.errorDisplay.showError(error as Error); - } - } - - // Enhanced UI methods - private async checkPermissions(): Promise { - try { - this.log('Checking permissions...'); - await this.permissionManager.updateStatus(); - this.log('✅ Permission status updated'); - } catch (error) { - this.log(`❌ Permission check failed: ${error}`); - this.errorDisplay.showError(error as Error); - } - } - - private async requestPermissions(): Promise { - try { - this.log('Requesting permissions...'); - this.permissionManager.showPermissionDialog(); - this.log('✅ Permission dialog shown'); - } catch (error) { - this.log(`❌ Permission request failed: ${error}`); - this.errorDisplay.showError(error as Error); - } - } - - private async openSettings(): Promise { - try { - this.log('Opening settings...'); - // Mock settings opening - this.log('✅ Settings opened (mock)'); - } catch (error) { - this.log(`❌ Settings open failed: ${error}`); - this.errorDisplay.showError(error as Error); - } - } - - private async testNotification(): Promise { - try { - this.log('Sending test notification...'); - // Mock test notification - this.log('✅ Test notification sent (mock)'); - } catch (error) { - this.log(`❌ Test notification failed: ${error}`); - this.errorDisplay.showError(error as Error); - } - } - - private async refreshStatus(): Promise { - try { - this.log('Refreshing status...'); - this.statusDashboard.render(); - this.log('✅ Status refreshed'); - } catch (error) { - this.log(`❌ Status refresh failed: ${error}`); - this.errorDisplay.showError(error as Error); - } - } - - private async checkServiceWorker(): Promise { - try { - this.log('Checking service worker status...'); - // Mock service worker status - this.log('✅ Service worker: Active (mock)'); - } catch (error) { - this.log(`❌ Service worker check failed: ${error}`); - this.errorDisplay.showError(error as Error); - } - } - - private async checkPushNotifications(): Promise { - try { - this.log('Checking push notification status...'); - // Mock push notification status - this.log('✅ Push notifications: Enabled (mock)'); - } catch (error) { - this.log(`❌ Push notification check failed: ${error}`); - this.errorDisplay.showError(error as Error); - } - } - - private async testConfigure(): Promise { - try { - this.log('Testing TimeSafari Electron configuration...'); - await this.configLoader.loadConfig(); - const config = this.configLoader.getConfig(); - - await this.notificationService.initialize(); - - this.log('✅ TimeSafari Electron configuration successful', { - appId: config.timesafari.appId, - appName: config.timesafari.appName, - version: config.timesafari.version - }); - this.updateStatus('Configured'); - } catch (error) { - this.log(`❌ Configuration failed: ${error}`); - } - } - - private async testSchedule(): Promise { - try { - this.log('Testing TimeSafari Electron community notification scheduling...'); - const config = this.configLoader.getConfig(); - - const dualConfig = { - contentFetch: { - enabled: true, - schedule: config.scheduling.contentFetch.schedule, - url: this.configLoader.getEndorserUrl('notificationsBundle'), - headers: this.configLoader.getAuthHeaders(), - ttlSeconds: 3600, - timeout: 30000, - retryAttempts: 3, - retryDelay: 5000, - callbacks: { - onSuccess: async (data: Record): Promise => { - this.log('✅ Content fetch successful', data); - await this.processEndorserNotificationBundle(data); - }, - onError: async (error: Record): Promise => { - this.log('❌ Content fetch failed', error); - } - } - }, - userNotification: { - enabled: true, - schedule: config.scheduling.userNotification.schedule, - title: 'TimeSafari Community Update', - body: 'New offers, projects, people, and items await your attention!', - sound: true, - vibration: true, - priority: 'high', - actions: [ - { id: 'view_offers', title: 'View Offers' }, - { id: 'view_projects', title: 'See Projects' }, - { id: 'view_people', title: 'Check People' }, - { id: 'view_items', title: 'Browse Items' }, - { id: 'dismiss', title: 'Dismiss' } - ] - }, - relationship: { - autoLink: true, - contentTimeout: 300000, - fallbackBehavior: 'show_default' - } - }; - - await this.notificationService.scheduleDualNotification(dualConfig); - this.log('✅ Electron community notification scheduled successfully'); - this.updateStatus('Scheduled'); - } catch (error) { - this.log(`❌ Electron scheduling failed: ${error}`); - } - } - - private async testEndorserAPI(): Promise { - try { - this.log('Testing Endorser.ch API integration on Electron...'); - const config = this.configLoader.getConfig(); - const testData = config.testData; - - // Test parallel API requests pattern - const requests = [ - // Offers to person - fetch(`${this.configLoader.getEndorserUrl('offers')}?recipientId=${testData.userDid}&afterId=${testData.lastKnownOfferId}`, { - headers: this.configLoader.getAuthHeaders() - }), - - // Offers to user's projects - fetch(`${this.configLoader.getEndorserUrl('offersToPlans')}?afterId=${testData.lastKnownOfferId}`, { - headers: this.configLoader.getAuthHeaders() - }), - - // Changes to starred projects - fetch(this.configLoader.getEndorserUrl('plansLastUpdated'), { - method: 'POST', - headers: this.configLoader.getAuthHeaders(), - body: JSON.stringify({ - planIds: testData.starredPlanIds, - afterId: testData.lastKnownPlanId - }) - }) - ]; - - const [offersToPerson, offersToProjects, starredChanges] = await Promise.all(requests); - - const notificationData = { - offersToPerson: await offersToPerson.json(), - offersToProjects: await offersToProjects.json(), - starredChanges: await starredChanges.json() - }; - - this.log('✅ Endorser.ch API integration successful on Electron', { - offersToPerson: notificationData.offersToPerson.data?.length || 0, - offersToProjects: notificationData.offersToProjects.data?.length || 0, - starredChanges: notificationData.starredChanges.data?.length || 0 - }); - - this.updateStatus('API Connected'); - } catch (error) { - this.log(`❌ Endorser.ch API test failed: ${error}`); - } - } - - private async testCallbacks(): Promise { - try { - this.log('Testing TimeSafari Electron notification callbacks...'); - // const config = this.configLoader.getConfig(); - - // Register offers callback - await this.notificationService.registerCallback('offers', async (event: Record) => { - this.log('📨 Electron Offers callback triggered', event); - await this.handleOffersNotification(event); - }); - - // Register projects callback - await this.notificationService.registerCallback('projects', async (event: Record) => { - this.log('📨 Electron Projects callback triggered', event); - await this.handleProjectsNotification(event); - }); - - // Register people callback - await this.notificationService.registerCallback('people', async (event: Record) => { - this.log('📨 Electron People callback triggered', event); - await this.handlePeopleNotification(event); - }); - - // Register items callback - await this.notificationService.registerCallback('items', async (event: Record) => { - this.log('📨 Electron Items callback triggered', event); - await this.handleItemsNotification(event); - }); - - this.log('✅ All Electron callbacks registered successfully'); - this.updateStatus('Callbacks Registered'); - } catch (error) { - this.log(`❌ Electron callback registration failed: ${error}`); - } - } - - private async testDebugInfo(): Promise { - try { - this.log('Testing Electron debug info...'); - const debugInfo = { - platform: 'electron', - nodeVersion: process.versions.node, - electronVersion: process.versions.electron, - chromeVersion: process.versions.chrome, - status: 'running', - config: this.configLoader.getConfig().timesafari, - timestamp: new Date().toISOString() - }; - - this.log('🔍 Electron Debug Info:', debugInfo); - this.updateStatus(`Debug: ${debugInfo.status}`); - } catch (error) { - this.log(`❌ Debug info failed: ${error}`); - } - } - - private async testPerformance(): Promise { - try { - this.log('Testing Electron performance metrics...'); - const metrics = { - overallScore: 82, - databasePerformance: 85, - memoryEfficiency: 78, - batteryEfficiency: 80, - objectPoolEfficiency: 85, - totalDatabaseQueries: 100, - averageMemoryUsage: 30.2, - objectPoolHits: 25, - backgroundCpuUsage: 3.1, - totalNetworkRequests: 15, - recommendations: ['Optimize IPC communication', 'Reduce memory usage'] - }; - - this.log('📊 Electron Performance Metrics:', metrics); - this.updateStatus(`Performance: ${metrics.overallScore}/100`); - } catch (error) { - this.log(`❌ Performance check failed: ${error}`); - } - } - - /** - * Process Endorser.ch notification bundle using parallel API requests - */ - private async processEndorserNotificationBundle(data: Record): Promise { - try { - this.log('Processing Endorser.ch notification bundle on Electron...'); - - // Process each notification type - if (data.offersToPerson?.data?.length > 0) { - await this.handleOffersNotification(data.offersToPerson); - } - - if (data.starredChanges?.data?.length > 0) { - await this.handleProjectsNotification(data.starredChanges); - } - - this.log('✅ Electron notification bundle processed successfully'); - } catch (error) { - this.log(`❌ Electron bundle processing failed: ${error}`); - } - } - - /** - * Handle offers notification events from Endorser.ch API - */ - private async handleOffersNotification(event: Record): Promise { - this.log('Handling Electron offers notification:', event); - - if (event.data && event.data.length > 0) { - // Process OfferSummaryArrayMaybeMoreBody format - event.data.forEach((offer: Record) => { - this.log('Processing Electron offer:', { - jwtId: offer.jwtId, - handleId: offer.handleId, - offeredByDid: offer.offeredByDid, - recipientDid: offer.recipientDid, - objectDescription: offer.objectDescription - }); - }); - - // Check if there are more offers to fetch - if (event.hitLimit) { - const lastOffer = event.data[event.data.length - 1]; - this.log('More offers available, last JWT ID:', lastOffer.jwtId); - } - } - } - - /** - * Handle projects notification events from Endorser.ch API - */ - private async handleProjectsNotification(event: Record): Promise { - this.log('Handling Electron projects notification:', event); - - if (event.data && event.data.length > 0) { - // Process PlanSummaryAndPreviousClaimArrayMaybeMore format - event.data.forEach((planData: Record) => { - const { plan, wrappedClaimBefore } = planData; - this.log('Processing Electron project change:', { - jwtId: plan.jwtId, - handleId: plan.handleId, - name: plan.name, - issuerDid: plan.issuerDid, - hasPreviousClaim: !!wrappedClaimBefore - }); - }); - - // Check if there are more project changes to fetch - if (event.hitLimit) { - const lastPlan = event.data[event.data.length - 1]; - this.log('More project changes available, last JWT ID:', lastPlan.plan.jwtId); - } - } - } - - /** - * Handle people notification events - */ - private async handlePeopleNotification(event: Record): Promise { - this.log('Handling Electron people notification:', event); - // Implementation would process people data and update local state - } - - /** - * Handle items notification events - */ - private async handleItemsNotification(event: Record): Promise { - this.log('Handling Electron items notification:', event); - // Implementation would process items data and update local state - } - - private log(message: string, data?: Record): void { - const timestamp = new Date().toLocaleTimeString(); - const logEntry = document.createElement('div'); - logEntry.innerHTML = `[${timestamp}] ${message}`; - if (data) { - logEntry.innerHTML += `
${JSON.stringify(data, null, 2)}
`; - } - this.logElement.appendChild(logEntry); - this.logElement.scrollTop = this.logElement.scrollHeight; - } - - private clearLog(): void { - this.logElement.innerHTML = ''; - this.log('Log cleared'); - } - - private updateStatus(status: string): void { - this.statusElement.textContent = status; - } - - // Phase 4: TimeSafari component test methods - private async testSecurityManager(): Promise { - try { - this.log('🔐 Testing SecurityManager (Electron)...'); - - // const timeSafariUser = this.configLoader.getTimeSafariUser(); - - // Test JWT generation - const jwt = await this.securityManager.generateJWT({ - scope: 'test', - audience: 'test-api' - }); - - if (jwt) { - this.log('✅ JWT generation successful'); - this.log('JWT token:', jwt.substring(0, 50) + '...'); - - // Test JWT verification - const claims = await this.securityManager.verifyJWT(jwt); - if (claims) { - this.log('✅ JWT verification successful'); - this.log('Claims:', claims); - } else { - this.log('❌ JWT verification failed'); - } - } else { - this.log('❌ JWT generation failed'); - } - - // Test operation history - const history = this.securityManager.getOperationHistory(); - this.log(`Security operations performed: ${history.length}`); - - this.log('SecurityManager test completed'); - - } catch (error) { - this.log('SecurityManager test failed:', error); - this.errorDisplay.showError(error as Error); - } - } - - private async testEndorserAPIClient(): Promise { - try { - this.log('🌐 Testing EndorserAPIClient (Electron)...'); - - const timeSafariUser = this.configLoader.getTimeSafariUser(); - - // Test offers to person - this.log('Testing offers to person...'); - const offersResponse = await this.endorserAPIClient.fetchOffersToPerson( - timeSafariUser.activeDid, - timeSafariUser.lastKnownOfferId, - undefined - ); - - this.log(`✅ Offers fetched: ${offersResponse.data.length} offers`); - if (offersResponse.data.length > 0) { - this.log('Sample offer:', offersResponse.data[0]); - } - - // Test offers to projects - this.log('Testing offers to projects...'); - const projectsResponse = await this.endorserAPIClient.fetchOffersToProjectsOwnedByMe( - timeSafariUser.lastKnownOfferId - ); - - this.log(`✅ Project offers fetched: ${projectsResponse.data.length} offers`); - - // Test project updates - if (timeSafariUser.starredPlanIds && timeSafariUser.starredPlanIds.length > 0) { - this.log('Testing project updates...'); - const updatesResponse = await this.endorserAPIClient.fetchProjectsLastUpdated( - timeSafariUser.starredPlanIds, - timeSafariUser.lastKnownPlanId, - undefined - ); - - this.log(`✅ Project updates fetched: ${updatesResponse.data.length} updates`); - } - - this.log('EndorserAPIClient test completed'); - - } catch (error) { - this.log('EndorserAPIClient test failed:', error); - this.errorDisplay.showError(error as Error); - } - } - - private async testTimeSafariNotificationManager(): Promise { - try { - this.log('📱 Testing TimeSafariNotificationManager (Electron)...'); - - // Test notification generation - this.log('Generating TimeSafari notifications...'); - const notifications = await this.timeSafariNotificationManager.generateNotifications({ - forceFetch: false, - includeMetadata: true, - filterByPriority: true, - maxNotifications: 10, - cacheTtl: 300000 - }); - - this.log(`✅ Generated ${notifications.length} notifications`); - - // Display notification details - notifications.forEach((notification, index) => { - this.log(`Notification ${index + 1}:`, { - type: notification.type, - subtype: notification.subtype, - priority: notification.notificationPriority, - timestamp: new Date(notification.timestamp).toISOString(), - disabled: notification.disabled, - sound: notification.sound, - vibration: notification.vibration - }); - }); - - // Test statistics - const stats = this.timeSafariNotificationManager.getStatistics(); - this.log('Manager statistics:', stats); - - this.log('TimeSafariNotificationManager test completed'); - - } catch (error) { - this.log('TimeSafariNotificationManager test failed:', error); - this.errorDisplay.showError(error as Error); - } - } - - private async testPhase4Integration(): Promise { - try { - this.log('🚀 Testing complete Phase 4 integration (Electron)...'); - - const timeSafariUser = this.configLoader.getTimeSafariUser(); - - // Test complete workflow - this.log('Step 1: Security authentication...'); - const jwt = await this.securityManager.generateJWT({ - scope: 'notifications', - audience: 'endorser-api' - }); - - if (!jwt) { - throw new Error('JWT generation failed'); - } - - this.endorserAPIClient.setAuthToken(jwt); - this.log('✅ Authentication successful'); - - this.log('Step 2: Fetching TimeSafari data...'); - const bundle = await this.endorserAPIClient.fetchAllTimeSafariNotifications({ - activeDid: timeSafariUser.activeDid, - starredPlanIds: timeSafariUser.starredPlanIds || [], - lastKnownOfferId: timeSafariUser.lastKnownOfferId, - lastKnownPlanId: timeSafariUser.lastKnownPlanId, - fetchOffersToPerson: true, - fetchOffersToProjects: true, - fetchProjectUpdates: true, - notificationPreferences: { - offers: true, - projects: true, - people: false, - items: true - } - }); - - this.log(`✅ Data fetched successfully: ${bundle.success}`); - this.log('Bundle metadata:', bundle.metadata); - - this.log('Step 3: Generating notifications...'); - const notifications = await this.timeSafariNotificationManager.generateNotifications({ - forceFetch: true, - includeMetadata: true, - maxNotifications: 20 - }); - - this.log(`✅ Generated ${notifications.length} notifications`); - - // Summary - this.log('🎉 Phase 4 integration test completed successfully!'); - this.log('Summary:', { - securityInitialized: this.securityManager.isInitialized(), - apiClientReady: !!this.endorserAPIClient, - managerInitialized: this.timeSafariNotificationManager.isInitialized(), - notificationsGenerated: notifications.length, - bundleSuccess: bundle.success - }); - - } catch (error) { - this.log('Phase 4 integration test failed:', error); - this.errorDisplay.showError(error as Error); - } - } - - // Static Daily Reminder Methods - private async scheduleDailyReminder(): Promise { - try { - this.log('Scheduling daily reminder...'); - - const reminderOptions = { - id: (document.getElementById('reminder-id') as HTMLInputElement)?.value || 'morning_checkin', - title: (document.getElementById('reminder-title') as HTMLInputElement)?.value || 'Good Morning!', - body: (document.getElementById('reminder-body') as HTMLInputElement)?.value || 'Time to check your TimeSafari community updates', - time: (document.getElementById('reminder-time') as HTMLInputElement)?.value || '09:00', - sound: (document.getElementById('reminder-sound') as HTMLInputElement)?.checked ?? true, - vibration: (document.getElementById('reminder-vibration') as HTMLInputElement)?.checked ?? true, - priority: (document.getElementById('reminder-priority') as HTMLSelectElement)?.value || 'normal', - repeatDaily: (document.getElementById('reminder-repeat') as HTMLInputElement)?.checked ?? true - }; - - this.log('Reminder options:', reminderOptions); - - await this.plugin.scheduleDailyReminder(reminderOptions); - this.log('✅ Daily reminder scheduled successfully'); - this.errorDisplay.showSuccess('Daily reminder scheduled successfully!'); - - } catch (error) { - this.log('❌ Failed to schedule daily reminder:', error); - this.errorDisplay.showError(error as Error); - } - } - - private async cancelDailyReminder(): Promise { - try { - this.log('Cancelling daily reminder...'); - - const reminderId = (document.getElementById('reminder-id') as HTMLInputElement)?.value || 'morning_checkin'; - - await this.plugin.cancelDailyReminder(reminderId); - this.log('✅ Daily reminder cancelled successfully'); - this.errorDisplay.showSuccess('Daily reminder cancelled successfully!'); - - } catch (error) { - this.log('❌ Failed to cancel daily reminder:', error); - this.errorDisplay.showError(error as Error); - } - } - - private async getScheduledReminders(): Promise { - try { - this.log('Getting scheduled reminders...'); - - const result = await this.plugin.getScheduledReminders(); - this.log('✅ Scheduled reminders retrieved:', result); - - if (result.reminders && result.reminders.length > 0) { - this.errorDisplay.showSuccess(`Found ${result.reminders.length} scheduled reminders`); - // eslint-disable-next-line no-console - console.table(result.reminders); - } else { - this.errorDisplay.showInfo('No scheduled reminders found'); - } - - } catch (error) { - this.log('❌ Failed to get scheduled reminders:', error); - this.errorDisplay.showError(error as Error); - } - } - - private async updateDailyReminder(): Promise { - try { - this.log('Updating daily reminder...'); - - const reminderId = (document.getElementById('reminder-id') as HTMLInputElement)?.value || 'morning_checkin'; - - const updateOptions = { - title: (document.getElementById('reminder-title') as HTMLInputElement)?.value, - body: (document.getElementById('reminder-body') as HTMLInputElement)?.value, - time: (document.getElementById('reminder-time') as HTMLInputElement)?.value, - sound: (document.getElementById('reminder-sound') as HTMLInputElement)?.checked, - vibration: (document.getElementById('reminder-vibration') as HTMLInputElement)?.checked, - priority: (document.getElementById('reminder-priority') as HTMLSelectElement)?.value, - repeatDaily: (document.getElementById('reminder-repeat') as HTMLInputElement)?.checked - }; - - this.log('Update options:', updateOptions); - - await this.plugin.updateDailyReminder(reminderId, updateOptions); - this.log('✅ Daily reminder updated successfully'); - this.errorDisplay.showSuccess('Daily reminder updated successfully!'); - - } catch (error) { - this.log('❌ Failed to update daily reminder:', error); - this.errorDisplay.showError(error as Error); - } - } -} - -// Initialize app when DOM is ready -document.addEventListener('DOMContentLoaded', () => { - new TimeSafariElectronTestApp(); -}); diff --git a/test-apps/electron-test/tsconfig.json b/test-apps/electron-test/tsconfig.json deleted file mode 100644 index aa6eba6..0000000 --- a/test-apps/electron-test/tsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "module": "ES2020", - "moduleResolution": "node", - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "outDir": "./dist", - "rootDir": "./src" - }, - "include": ["src/**/*"], - "exclude": ["node_modules", "dist"] -} diff --git a/test-apps/electron-test/webpack.config.js b/test-apps/electron-test/webpack.config.js deleted file mode 100644 index a818f67..0000000 --- a/test-apps/electron-test/webpack.config.js +++ /dev/null @@ -1,28 +0,0 @@ -const path = require('path'); -const HtmlWebpackPlugin = require('html-webpack-plugin'); - -module.exports = { - entry: './src/index.ts', - module: { - rules: [ - { - test: /\.ts$/, - use: 'ts-loader', - exclude: /node_modules/, - }, - ], - }, - resolve: { - extensions: ['.ts', '.js'], - }, - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist'), - clean: true, - }, - plugins: [ - new HtmlWebpackPlugin({ - template: './src/index.html', - }), - ], -}; diff --git a/test-apps/ios-test/.gitignore b/test-apps/ios-test/.gitignore deleted file mode 100644 index a217c10..0000000 --- a/test-apps/ios-test/.gitignore +++ /dev/null @@ -1,105 +0,0 @@ -# Dependencies -node_modules/ -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# Build outputs -dist/ -build/ -*.tsbuildinfo - -# Capacitor -android/ -ios/ -.capacitor/ - -# IDE and editor files -.vscode/ -.idea/ -*.swp -*.swo -*~ - -# OS generated files -.DS_Store -.DS_Store? -._* -.Spotlight-V100 -.Trashes -ehthumbs.db -Thumbs.db - -# Logs -logs -*.log - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Coverage directory used by tools like istanbul -coverage/ -*.lcov - -# nyc test coverage -.nyc_output - -# Dependency directories -jspm_packages/ - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Microbundle cache -.rpt2_cache/ -.rts2_cache_cjs/ -.rts2_cache_es/ -.rts2_cache_umd/ - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -.env -.env.test -.env.local -.env.development.local -.env.test.local -.env.production.local - -# parcel-bundler cache (https://parceljs.org/) -.cache -.parcel-cache - -# next.js build output -.next - -# nuxt.js build output -.nuxt - -# vuepress build output -.vuepress/dist - -# Serverless directories -.serverless/ - -# FuseBox cache -.fusebox/ - -# DynamoDB Local files -.dynamodb/ - -# TernJS port file -.tern-port diff --git a/test-apps/ios-test/capacitor.config.ts b/test-apps/ios-test/capacitor.config.ts deleted file mode 100644 index 0e88c7b..0000000 --- a/test-apps/ios-test/capacitor.config.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { CapacitorConfig } from '@capacitor/cli'; - -const config: CapacitorConfig = { - appId: 'com.timesafari.dailynotification.iostest', - appName: 'Daily Notification iOS Test', - webDir: 'dist', - server: { - iosScheme: 'capacitor' - }, - plugins: { - DailyNotification: { - storage: 'shared', - ttlSeconds: 1800, - prefetchLeadMinutes: 15, - enableETagSupport: true, - enableErrorHandling: true, - enablePerformanceOptimization: true - } - }, - ios: { - scheme: 'Daily Notification iOS Test' - } -}; - -export default config; diff --git a/test-apps/ios-test/package.json b/test-apps/ios-test/package.json deleted file mode 100644 index 38d2b81..0000000 --- a/test-apps/ios-test/package.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "daily-notification-ios-test", - "version": "1.0.0", - "description": "Minimal iOS test app for Daily Notification Plugin", - "main": "index.js", - "scripts": { - "build": "webpack --mode=production", - "dev": "webpack serve --mode=development", - "ios": "npx cap run ios", - "sync": "npx cap sync ios", - "open": "npx cap open ios" - }, - "keywords": ["capacitor", "ios", "notifications", "test"], - "author": "Matthew Raymer", - "license": "MIT", - "dependencies": { - "@capacitor/core": "^5.0.0", - "@capacitor/ios": "^5.0.0", - "@capacitor/cli": "^5.0.0" - }, - "devDependencies": { - "webpack": "^5.88.0", - "webpack-cli": "^5.1.0", - "webpack-dev-server": "^4.15.0", - "html-webpack-plugin": "^5.5.0", - "typescript": "^5.0.0", - "ts-loader": "^9.4.0" - } -} diff --git a/test-apps/ios-test/src/index.html b/test-apps/ios-test/src/index.html deleted file mode 100644 index ab1241f..0000000 --- a/test-apps/ios-test/src/index.html +++ /dev/null @@ -1,476 +0,0 @@ - - - - - - Daily Notification - iOS Test - - - -
-

🍎 TimeSafari Daily Notification - iOS Test

- -
Ready
- - -
-

🔐 Permission Management

-
-
- - - -
-
- - -
-

⚙️ Configuration

-
-
- - -
-
- - -
-

📊 Status Monitoring

-
-
- - -
-
- - -
-

🍎 iOS-Specific Features

-
-
- - - -
-
- - -
-

🧪 Testing & Debug

-
- - - - -
-
- - -
-

🚀 Phase 4: TimeSafari Components

-
- - - - -
-
- - -
-

⏰ Static Daily Reminders

-
- - - - -
-
-

Reminder Configuration

-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- -
-
-
- - -
-

⚠️ Error Handling

-
-
- - -
-

📝 Activity Log

-
- -
-
- - -
- - - - diff --git a/test-apps/ios-test/src/index.ts b/test-apps/ios-test/src/index.ts deleted file mode 100644 index 6efb729..0000000 --- a/test-apps/ios-test/src/index.ts +++ /dev/null @@ -1,1340 +0,0 @@ -// import { Capacitor } from '@capacitor/core'; -import { ConfigLoader, MockDailyNotificationService, TestLogger } from '../shared/config-loader'; - -// Phase 4: Import TimeSafari components -import { EndorserAPIClient } from '../shared/typescript/EndorserAPIClient'; -import { SecurityManager } from '../shared/typescript/SecurityManager'; -import { TimeSafariNotificationManager } from '../shared/typescript/TimeSafariNotificationManager'; -// import { -// TimeSafariUser, -// TimeSafariPreferences, -// EnhancedTimeSafariNotification, -// TimeSafariNotificationType -// } from '../../../src/definitions'; - -// Generic Polling Interface -import { - GenericPollingRequest, - PollingScheduleConfig, - PollingResult, - StarredProjectsRequest, - StarredProjectsResponse, - calculateBackoffDelay, - createDefaultOutboxPressureManager -} from '../../../packages/polling-contracts/src'; - -// Enhanced UI components for iOS testing -class PermissionManager { - private container: HTMLElement; - private dialogContainer: HTMLElement; - - constructor(container: HTMLElement, dialogContainer: HTMLElement) { - this.container = container; - this.dialogContainer = dialogContainer; - } - - async updateStatus(): Promise { - // Mock permission status for iOS testing - const mockStatus = { - granted: true, - notifications: 'granted' as const, - backgroundRefresh: 'granted' as const - }; - - this.renderStatus(mockStatus); - } - - private renderStatus(status: Record): void { - const statusClass = status.granted ? 'status-granted' : 'status-denied'; - const statusText = status.granted ? 'Granted' : 'Denied'; - - this.container.innerHTML = ` -
-
- ${status.granted ? '✓' : '✗'} - ${statusText} -
-
-
- Notifications: - - ${status.notifications} - -
-
- Background Refresh: - - ${status.backgroundRefresh} - -
-
-
- `; - } - - showPermissionDialog(): void { - const dialog = document.createElement('div'); - dialog.className = 'dialog-overlay'; - dialog.innerHTML = ` -
-

Enable Daily Notifications

-

Get notified about new offers, projects, people, and items in your TimeSafari community.

-
    -
  • New offers directed to you
  • -
  • Changes to your projects
  • -
  • Updates from favorited people
  • -
  • New items of interest
  • -
-
- - - -
-
- `; - - this.dialogContainer.appendChild(dialog); - - dialog.querySelector('#allow-permissions')?.addEventListener('click', () => { - this.hideDialog(); - this.updateStatus(); - }); - - dialog.querySelector('#deny-permissions')?.addEventListener('click', () => { - this.hideDialog(); - }); - - dialog.querySelector('#never-permissions')?.addEventListener('click', () => { - this.hideDialog(); - }); - } - - private hideDialog(): void { - const dialog = this.dialogContainer.querySelector('.dialog-overlay'); - if (dialog) { - dialog.remove(); - } - } -} - -class SettingsPanel { - private container: HTMLElement; - - constructor(container: HTMLElement) { - this.container = container; - } - - render(): void { - this.container.innerHTML = ` -
-
- -
- -
- - -
- -
- -
- - - - -
-
- -
- -
- - - -
-
- -
- -
-
- `; - } -} - -class StatusDashboard { - private container: HTMLElement; - - constructor(container: HTMLElement) { - this.container = container; - } - - render(): void { - this.container.innerHTML = ` -
-
-
-
Overall Status
-
Active
-
- -
-
Next Notification
-
2h 15m
-
- -
-
Last Outcome
-
Success
-
- -
-
Cache Age
-
1h 23m
-
-
- -
-

Performance

-
-
- Success Rate: - 95% -
-
- Error Count: - 2 -
-
-
-
- `; - } -} - -class ErrorDisplay { - private container: HTMLElement; - - constructor(container: HTMLElement) { - this.container = container; - } - - showError(error: Error): void { - this.container.innerHTML = ` -
-
⚠️
-
-

Something went wrong

-

${error.message}

-

Error Code: ${error.name}

-
-
- - -
-
- `; - } - - hide(): void { - this.container.innerHTML = ''; - } -} - -// Enhanced test interface for TimeSafari iOS integration with Phase 4 components -class TimeSafariIOSTestApp { - private statusElement: HTMLElement; - private logElement: HTMLElement; - private configLoader: ConfigLoader; - private notificationService: MockDailyNotificationService; - private logger: TestLogger; - - // Phase 4: TimeSafari components - private endorserAPIClient: EndorserAPIClient; - private securityManager: SecurityManager; - private timeSafariNotificationManager: TimeSafariNotificationManager; - - // UI Components - private permissionManager: PermissionManager; - private settingsPanel: SettingsPanel; - private statusDashboard: StatusDashboard; - private errorDisplay: ErrorDisplay; - - constructor() { - const statusElement = document.getElementById('status'); - const logElement = document.getElementById('log'); - if (!statusElement || !logElement) { - throw new Error('Required DOM elements not found'); - } - this.statusElement = statusElement; - this.logElement = logElement; - this.configLoader = ConfigLoader.getInstance(); - this.logger = new TestLogger('debug'); - this.notificationService = new MockDailyNotificationService(this.configLoader.getConfig()); - - // Phase 4: Initialize TimeSafari components - const endorserAPIConfig = this.configLoader.getEndorserAPIConfig(); - const securityConfig = this.configLoader.getSecurityConfig(); - if (!endorserAPIConfig || !securityConfig) { - throw new Error('Required configurations not found'); - } - this.endorserAPIClient = new EndorserAPIClient(endorserAPIConfig); - this.securityManager = new SecurityManager(securityConfig); - this.timeSafariNotificationManager = new TimeSafariNotificationManager(); - - // Initialize UI components - const permissionStatusContainer = document.getElementById('permission-status-container'); - const permissionDialogContainer = document.getElementById('permission-dialog-container'); - const settingsContainer = document.getElementById('settings-container'); - const statusContainer = document.getElementById('status-container'); - const errorContainer = document.getElementById('error-container'); - - if (!permissionStatusContainer || !permissionDialogContainer || !settingsContainer || !statusContainer || !errorContainer) { - throw new Error('Required UI containers not found'); - } - - this.permissionManager = new PermissionManager( - permissionStatusContainer, - permissionDialogContainer - ); - this.settingsPanel = new SettingsPanel(settingsContainer); - this.statusDashboard = new StatusDashboard(statusContainer); - this.errorDisplay = new ErrorDisplay(errorContainer); - - this.setupEventListeners(); - this.initializeUI(); - this.initializePhase4Components(); - this.log('TimeSafari iOS Test app initialized with Phase 4 components'); - } - - private setupEventListeners(): void { - // Original test functionality - document.getElementById('configure')?.addEventListener('click', () => this.testConfigure()); - document.getElementById('schedule')?.addEventListener('click', () => this.testSchedule()); - document.getElementById('rolling-window')?.addEventListener('click', () => this.testRollingWindow()); - document.getElementById('endorser-api')?.addEventListener('click', () => this.testEndorserAPI()); - document.getElementById('callbacks')?.addEventListener('click', () => this.testCallbacks()); - document.getElementById('performance')?.addEventListener('click', () => this.testPerformance()); - document.getElementById('clear-log')?.addEventListener('click', () => this.clearLog()); - - // Enhanced UI functionality - document.getElementById('check-permissions')?.addEventListener('click', () => this.checkPermissions()); - document.getElementById('request-permissions')?.addEventListener('click', () => this.requestPermissions()); - document.getElementById('open-settings')?.addEventListener('click', () => this.openSettings()); - document.getElementById('test-notification')?.addEventListener('click', () => this.testNotification()); - document.getElementById('check-status')?.addEventListener('click', () => this.testStatus()); - document.getElementById('refresh-status')?.addEventListener('click', () => this.refreshStatus()); - document.getElementById('background-refresh-status')?.addEventListener('click', () => this.checkBackgroundRefresh()); - document.getElementById('bg-task-status')?.addEventListener('click', () => this.checkBGTaskStatus()); - - // Phase 4: TimeSafari component testing - document.getElementById('test-security-manager')?.addEventListener('click', () => this.testSecurityManager()); - document.getElementById('test-endorser-api-client')?.addEventListener('click', () => this.testEndorserAPIClient()); - document.getElementById('test-notification-manager')?.addEventListener('click', () => this.testTimeSafariNotificationManager()); - document.getElementById('test-phase4-integration')?.addEventListener('click', () => this.testPhase4Integration()); - - // Generic Polling Interface testing - document.getElementById('test-generic-polling')?.addEventListener('click', () => this.testGenericPolling()); - document.getElementById('test-polling-schedule')?.addEventListener('click', () => this.testPollingSchedule()); - document.getElementById('test-polling-results')?.addEventListener('click', () => this.testPollingResults()); - - // Static Daily Reminder event listeners - document.getElementById('schedule-reminder')?.addEventListener('click', () => this.scheduleDailyReminder()); - document.getElementById('cancel-reminder')?.addEventListener('click', () => this.cancelDailyReminder()); - document.getElementById('get-reminders')?.addEventListener('click', () => this.getScheduledReminders()); - document.getElementById('update-reminder')?.addEventListener('click', () => this.updateDailyReminder()); - } - - private async initializeUI(): Promise { - try { - // Initialize UI components - await this.permissionManager.updateStatus(); - this.settingsPanel.render(); - this.statusDashboard.render(); - - this.log('✅ Enhanced UI components initialized'); - } catch (error) { - this.log(`❌ UI initialization failed: ${error}`); - this.errorDisplay.showError(error as Error); - } - } - - // Phase 4: Initialize TimeSafari components - private async initializePhase4Components(): Promise { - try { - this.log('Initializing Phase 4 TimeSafari components...'); - - // Initialize SecurityManager with test DID - const timeSafariUser = this.configLoader.getTimeSafariUser(); - const securityInitialized = await this.securityManager.initialize(timeSafariUser.activeDid); - - if (securityInitialized) { - this.log('✅ SecurityManager initialized successfully'); - - // Generate JWT token for API authentication - const jwt = await this.securityManager.generateJWT({ - scope: 'notifications', - audience: 'endorser-api' - }); - - if (jwt) { - this.endorserAPIClient.setAuthToken(jwt); - this.log('✅ JWT token generated and set for EndorserAPI'); - } - } else { - this.log('❌ SecurityManager initialization failed'); - } - - // Initialize TimeSafariNotificationManager - const managerInitialized = await this.timeSafariNotificationManager.initialize(timeSafariUser); - - if (managerInitialized) { - this.log('✅ TimeSafariNotificationManager initialized successfully'); - } else { - this.log('❌ TimeSafariNotificationManager initialization failed'); - } - - this.log('Phase 4 components initialization completed'); - - } catch (error) { - this.log('Error initializing Phase 4 components:', error); - this.errorDisplay.showError(error as Error); - } - } - - // Enhanced UI methods - private async checkPermissions(): Promise { - try { - this.log('Checking permissions...'); - await this.permissionManager.updateStatus(); - this.log('✅ Permission status updated'); - } catch (error) { - this.log(`❌ Permission check failed: ${error}`); - this.errorDisplay.showError(error as Error); - } - } - - private async requestPermissions(): Promise { - try { - this.log('Requesting permissions...'); - this.permissionManager.showPermissionDialog(); - this.log('✅ Permission dialog shown'); - } catch (error) { - this.log(`❌ Permission request failed: ${error}`); - this.errorDisplay.showError(error as Error); - } - } - - private async openSettings(): Promise { - try { - this.log('Opening settings...'); - // Mock settings opening - this.log('✅ Settings opened (mock)'); - } catch (error) { - this.log(`❌ Settings open failed: ${error}`); - this.errorDisplay.showError(error as Error); - } - } - - private async testNotification(): Promise { - try { - this.log('Sending test notification...'); - // Mock test notification - this.log('✅ Test notification sent (mock)'); - } catch (error) { - this.log(`❌ Test notification failed: ${error}`); - this.errorDisplay.showError(error as Error); - } - } - - private async refreshStatus(): Promise { - try { - this.log('Refreshing status...'); - this.statusDashboard.render(); - this.log('✅ Status refreshed'); - } catch (error) { - this.log(`❌ Status refresh failed: ${error}`); - this.errorDisplay.showError(error as Error); - } - } - - private async checkBackgroundRefresh(): Promise { - try { - this.log('Checking background app refresh status...'); - // Mock background refresh status - this.log('✅ Background app refresh: Enabled (mock)'); - } catch (error) { - this.log(`❌ Background refresh check failed: ${error}`); - this.errorDisplay.showError(error as Error); - } - } - - private async checkBGTaskStatus(): Promise { - try { - this.log('Checking BGTaskScheduler status...'); - // Mock BGTaskScheduler status - this.log('✅ BGTaskScheduler: Active (mock)'); - } catch (error) { - this.log(`❌ BGTaskScheduler check failed: ${error}`); - this.errorDisplay.showError(error as Error); - } - } - - private async testConfigure(): Promise { - try { - this.log('Testing TimeSafari iOS configuration...'); - await this.configLoader.loadConfig(); - const config = this.configLoader.getConfig(); - - await this.notificationService.initialize(); - - this.log('✅ TimeSafari iOS configuration successful', { - appId: config.timesafari.appId, - appName: config.timesafari.appName, - version: config.timesafari.version - }); - this.updateStatus('Configured'); - } catch (error) { - this.log(`❌ Configuration failed: ${error}`); - } - } - - private async testSchedule(): Promise { - try { - this.log('Testing TimeSafari iOS community notification scheduling...'); - const config = this.configLoader.getConfig(); - - const dualConfig = { - contentFetch: { - enabled: true, - schedule: config.scheduling.contentFetch.schedule, - url: this.configLoader.getEndorserUrl('notificationsBundle'), - headers: this.configLoader.getAuthHeaders(), - ttlSeconds: 3600, - timeout: 30000, - retryAttempts: 3, - retryDelay: 5000, - callbacks: { - onSuccess: async (data: Record): Promise => { - this.log('✅ Content fetch successful', data); - await this.processEndorserNotificationBundle(data); - }, - onError: async (error: Record): Promise => { - this.log('❌ Content fetch failed', error); - } - } - }, - userNotification: { - enabled: true, - schedule: config.scheduling.userNotification.schedule, - title: 'TimeSafari Community Update', - body: 'New offers, projects, people, and items await your attention!', - sound: true, - vibration: true, - priority: 'high', - actions: [ - { id: 'view_offers', title: 'View Offers' }, - { id: 'view_projects', title: 'See Projects' }, - { id: 'view_people', title: 'Check People' }, - { id: 'view_items', title: 'Browse Items' }, - { id: 'dismiss', title: 'Dismiss' } - ] - }, - relationship: { - autoLink: true, - contentTimeout: 300000, - fallbackBehavior: 'show_default' - } - }; - - await this.notificationService.scheduleDualNotification(dualConfig); - this.log('✅ iOS community notification scheduled successfully'); - this.updateStatus('Scheduled'); - } catch (error) { - this.log(`❌ iOS scheduling failed: ${error}`); - } - } - - private async testRollingWindow(): Promise { - try { - this.log('Testing iOS rolling window maintenance...'); - // Simulate rolling window maintenance - const stats = { - stats: '64 pending notifications, 20 daily limit', - maintenanceNeeded: false, - timeUntilNextMaintenance: 900000 - }; - - this.log('✅ Rolling window maintenance completed', stats); - this.updateStatus('Rolling Window Maintained'); - } catch (error) { - this.log(`❌ Rolling window maintenance failed: ${error}`); - } - } - - private async testEndorserAPI(): Promise { - try { - this.log('Testing Endorser.ch API integration on iOS...'); - const config = this.configLoader.getConfig(); - const testData = config.testData; - - // Test parallel API requests pattern - const requests = [ - // Offers to person - fetch(`${this.configLoader.getEndorserUrl('offers')}?recipientId=${testData.userDid}&afterId=${testData.lastKnownOfferId}`, { - headers: this.configLoader.getAuthHeaders() - }), - - // Offers to user's projects - fetch(`${this.configLoader.getEndorserUrl('offersToPlans')}?afterId=${testData.lastKnownOfferId}`, { - headers: this.configLoader.getAuthHeaders() - }), - - // Changes to starred projects - fetch(this.configLoader.getEndorserUrl('plansLastUpdated'), { - method: 'POST', - headers: this.configLoader.getAuthHeaders(), - body: JSON.stringify({ - planIds: testData.starredPlanIds, - afterId: testData.lastKnownPlanId - }) - }) - ]; - - const [offersToPerson, offersToProjects, starredChanges] = await Promise.all(requests); - - const notificationData = { - offersToPerson: await offersToPerson.json(), - offersToProjects: await offersToProjects.json(), - starredChanges: await starredChanges.json() - }; - - this.log('✅ Endorser.ch API integration successful on iOS', { - offersToPerson: notificationData.offersToPerson.data?.length || 0, - offersToProjects: notificationData.offersToProjects.data?.length || 0, - starredChanges: notificationData.starredChanges.data?.length || 0 - }); - - this.updateStatus('API Connected'); - } catch (error) { - this.log(`❌ Endorser.ch API test failed: ${error}`); - } - } - - private async testCallbacks(): Promise { - try { - this.log('Testing TimeSafari iOS notification callbacks...'); - // const config = this.configLoader.getConfig(); - - // Register offers callback - await this.notificationService.registerCallback('offers', async (event: Record) => { - this.log('📨 iOS Offers callback triggered', event); - await this.handleOffersNotification(event); - }); - - // Register projects callback - await this.notificationService.registerCallback('projects', async (event: Record) => { - this.log('📨 iOS Projects callback triggered', event); - await this.handleProjectsNotification(event); - }); - - // Register people callback - await this.notificationService.registerCallback('people', async (event: Record) => { - this.log('📨 iOS People callback triggered', event); - await this.handlePeopleNotification(event); - }); - - // Register items callback - await this.notificationService.registerCallback('items', async (event: Record) => { - this.log('📨 iOS Items callback triggered', event); - await this.handleItemsNotification(event); - }); - - this.log('✅ All iOS callbacks registered successfully'); - this.updateStatus('Callbacks Registered'); - } catch (error) { - this.log(`❌ iOS callback registration failed: ${error}`); - } - } - - private async testPerformance(): Promise { - try { - this.log('Testing iOS performance metrics...'); - const metrics = { - overallScore: 88, - databasePerformance: 92, - memoryEfficiency: 85, - batteryEfficiency: 90, - objectPoolEfficiency: 88, - totalDatabaseQueries: 120, - averageMemoryUsage: 22.3, - objectPoolHits: 38, - backgroundCpuUsage: 1.8, - totalNetworkRequests: 8, - recommendations: ['Enable background tasks', 'Optimize memory usage'] - }; - - this.log('📊 iOS Performance Metrics:', metrics); - this.updateStatus(`Performance: ${metrics.overallScore}/100`); - } catch (error) { - this.log(`❌ Performance check failed: ${error}`); - } - } - - /** - * Process Endorser.ch notification bundle using parallel API requests - */ - private async processEndorserNotificationBundle(data: Record): Promise { - try { - this.log('Processing Endorser.ch notification bundle on iOS...'); - - // Process each notification type - if (data.offersToPerson?.data?.length > 0) { - await this.handleOffersNotification(data.offersToPerson); - } - - if (data.starredChanges?.data?.length > 0) { - await this.handleProjectsNotification(data.starredChanges); - } - - this.log('✅ iOS notification bundle processed successfully'); - } catch (error) { - this.log(`❌ iOS bundle processing failed: ${error}`); - } - } - - /** - * Handle offers notification events from Endorser.ch API - */ - private async handleOffersNotification(event: Record): Promise { - this.log('Handling iOS offers notification:', event); - - if (event.data && event.data.length > 0) { - // Process OfferSummaryArrayMaybeMoreBody format - event.data.forEach((offer: Record) => { - this.log('Processing iOS offer:', { - jwtId: offer.jwtId, - handleId: offer.handleId, - offeredByDid: offer.offeredByDid, - recipientDid: offer.recipientDid, - objectDescription: offer.objectDescription - }); - }); - - // Check if there are more offers to fetch - if (event.hitLimit) { - const lastOffer = event.data[event.data.length - 1]; - this.log('More offers available, last JWT ID:', lastOffer.jwtId); - } - } - } - - /** - * Handle projects notification events from Endorser.ch API - */ - private async handleProjectsNotification(event: Record): Promise { - this.log('Handling iOS projects notification:', event); - - if (event.data && event.data.length > 0) { - // Process PlanSummaryAndPreviousClaimArrayMaybeMore format - event.data.forEach((planData: Record) => { - const { plan, wrappedClaimBefore } = planData; - this.log('Processing iOS project change:', { - jwtId: plan.jwtId, - handleId: plan.handleId, - name: plan.name, - issuerDid: plan.issuerDid, - hasPreviousClaim: !!wrappedClaimBefore - }); - }); - - // Check if there are more project changes to fetch - if (event.hitLimit) { - const lastPlan = event.data[event.data.length - 1]; - this.log('More project changes available, last JWT ID:', lastPlan.plan.jwtId); - } - } - } - - /** - * Handle people notification events - */ - private async handlePeopleNotification(event: Record): Promise { - this.log('Handling iOS people notification:', event); - // Implementation would process people data and update local state - } - - /** - * Handle items notification events - */ - private async handleItemsNotification(event: Record): Promise { - this.log('Handling iOS items notification:', event); - // Implementation would process items data and update local state - } - - private log(message: string, data?: Record): void { - const timestamp = new Date().toLocaleTimeString(); - const logEntry = document.createElement('div'); - logEntry.innerHTML = `[${timestamp}] ${message}`; - if (data) { - logEntry.innerHTML += `
${JSON.stringify(data, null, 2)}
`; - } - this.logElement.appendChild(logEntry); - this.logElement.scrollTop = this.logElement.scrollHeight; - } - - private clearLog(): void { - this.logElement.innerHTML = ''; - this.log('Log cleared'); - } - - private updateStatus(status: string): void { - this.statusElement.textContent = status; - } - - // Phase 4: TimeSafari component test methods - private async testSecurityManager(): Promise { - try { - this.log('🔐 Testing SecurityManager (iOS)...'); - - // const timeSafariUser = this.configLoader.getTimeSafariUser(); - - // Test JWT generation - const jwt = await this.securityManager.generateJWT({ - scope: 'test', - audience: 'test-api' - }); - - if (jwt) { - this.log('✅ JWT generation successful'); - this.log('JWT token:', jwt.substring(0, 50) + '...'); - - // Test JWT verification - const claims = await this.securityManager.verifyJWT(jwt); - if (claims) { - this.log('✅ JWT verification successful'); - this.log('Claims:', claims); - } else { - this.log('❌ JWT verification failed'); - } - } else { - this.log('❌ JWT generation failed'); - } - - // Test operation history - const history = this.securityManager.getOperationHistory(); - this.log(`Security operations performed: ${history.length}`); - - this.log('SecurityManager test completed'); - - } catch (error) { - this.log('SecurityManager test failed:', error); - this.errorDisplay.showError(error as Error); - } - } - - private async testEndorserAPIClient(): Promise { - try { - this.log('🌐 Testing EndorserAPIClient (iOS)...'); - - const timeSafariUser = this.configLoader.getTimeSafariUser(); - - // Test offers to person - this.log('Testing offers to person...'); - const offersResponse = await this.endorserAPIClient.fetchOffersToPerson( - timeSafariUser.activeDid, - timeSafariUser.lastKnownOfferId, - undefined - ); - - this.log(`✅ Offers fetched: ${offersResponse.data.length} offers`); - if (offersResponse.data.length > 0) { - this.log('Sample offer:', offersResponse.data[0]); - } - - // Test offers to projects - this.log('Testing offers to projects...'); - const projectsResponse = await this.endorserAPIClient.fetchOffersToProjectsOwnedByMe( - timeSafariUser.lastKnownOfferId - ); - - this.log(`✅ Project offers fetched: ${projectsResponse.data.length} offers`); - - // Test project updates - if (timeSafariUser.starredPlanIds && timeSafariUser.starredPlanIds.length > 0) { - this.log('Testing project updates...'); - const updatesResponse = await this.endorserAPIClient.fetchProjectsLastUpdated( - timeSafariUser.starredPlanIds, - timeSafariUser.lastKnownPlanId, - undefined - ); - - this.log(`✅ Project updates fetched: ${updatesResponse.data.length} updates`); - } - - this.log('EndorserAPIClient test completed'); - - } catch (error) { - this.log('EndorserAPIClient test failed:', error); - this.errorDisplay.showError(error as Error); - } - } - - private async testTimeSafariNotificationManager(): Promise { - try { - this.log('📱 Testing TimeSafariNotificationManager (iOS)...'); - - // Test notification generation - this.log('Generating TimeSafari notifications...'); - const notifications = await this.timeSafariNotificationManager.generateNotifications({ - forceFetch: false, - includeMetadata: true, - filterByPriority: true, - maxNotifications: 10, - cacheTtl: 300000 - }); - - this.log(`✅ Generated ${notifications.length} notifications`); - - // Display notification details - notifications.forEach((notification, index) => { - this.log(`Notification ${index + 1}:`, { - type: notification.type, - subtype: notification.subtype, - priority: notification.notificationPriority, - timestamp: new Date(notification.timestamp).toISOString(), - disabled: notification.disabled, - sound: notification.sound, - vibration: notification.vibration - }); - }); - - // Test statistics - const stats = this.timeSafariNotificationManager.getStatistics(); - this.log('Manager statistics:', stats); - - this.log('TimeSafariNotificationManager test completed'); - - } catch (error) { - this.log('TimeSafariNotificationManager test failed:', error); - this.errorDisplay.showError(error as Error); - } - } - - private async testPhase4Integration(): Promise { - try { - this.log('🚀 Testing complete Phase 4 integration (iOS)...'); - - const timeSafariUser = this.configLoader.getTimeSafariUser(); - - // Test complete workflow - this.log('Step 1: Security authentication...'); - const jwt = await this.securityManager.generateJWT({ - scope: 'notifications', - audience: 'endorser-api' - }); - - if (!jwt) { - throw new Error('JWT generation failed'); - } - - this.endorserAPIClient.setAuthToken(jwt); - this.log('✅ Authentication successful'); - - this.log('Step 2: Fetching TimeSafari data...'); - const bundle = await this.endorserAPIClient.fetchAllTimeSafariNotifications({ - activeDid: timeSafariUser.activeDid, - starredPlanIds: timeSafariUser.starredPlanIds || [], - lastKnownOfferId: timeSafariUser.lastKnownOfferId, - lastKnownPlanId: timeSafariUser.lastKnownPlanId, - fetchOffersToPerson: true, - fetchOffersToProjects: true, - fetchProjectUpdates: true, - notificationPreferences: { - offers: true, - projects: true, - people: false, - items: true - } - }); - - this.log(`✅ Data fetched successfully: ${bundle.success}`); - this.log('Bundle metadata:', bundle.metadata); - - this.log('Step 3: Generating notifications...'); - const notifications = await this.timeSafariNotificationManager.generateNotifications({ - forceFetch: true, - includeMetadata: true, - maxNotifications: 20 - }); - - this.log(`✅ Generated ${notifications.length} notifications`); - - // Summary - this.log('🎉 Phase 4 integration test completed successfully!'); - this.log('Summary:', { - securityInitialized: this.securityManager.isInitialized(), - apiClientReady: !!this.endorserAPIClient, - managerInitialized: this.timeSafariNotificationManager.isInitialized(), - notificationsGenerated: notifications.length, - bundleSuccess: bundle.success - }); - - } catch (error) { - this.log('Phase 4 integration test failed:', error); - this.errorDisplay.showError(error as Error); - } - } - - // Generic Polling Interface Test Methods - private async testGenericPolling(): Promise { - try { - this.log('🔄 Testing Generic Polling Interface (iOS)...'); - - // Create a starred projects polling request - const starredProjectsRequest: GenericPollingRequest = { - endpoint: '/api/v2/report/plansLastUpdatedBetween', - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'User-Agent': 'TimeSafari-DailyNotificationPlugin/1.0.0', - 'Authorization': `Bearer ${await this.getJwtToken()}` - }, - body: { - planIds: ['plan:test-1', 'plan:test-2'], - afterId: '1704067200_abc123_12345678', - limit: 100 - }, - responseSchema: { - validate: (data: unknown): data is StarredProjectsResponse => { - return data && - Array.isArray(data.data) && - typeof data.hitLimit === 'boolean' && - data.pagination && - typeof data.pagination.hasMore === 'boolean'; - }, - transformError: (error: unknown) => ({ - code: 'VALIDATION_ERROR', - message: error.message || 'Validation failed', - retryable: false - }) - }, - retryConfig: { - maxAttempts: 3, - backoffStrategy: 'exponential', - baseDelayMs: 1000 - }, - timeoutMs: 30000 - }; - - this.log('✅ Generic polling request created successfully'); - this.log('Request details:', { - endpoint: starredProjectsRequest.endpoint, - method: starredProjectsRequest.method, - planIds: starredProjectsRequest.body.planIds, - afterId: starredProjectsRequest.body.afterId - }); - - // Test backoff calculation - const backoffDelay = calculateBackoffDelay(1, starredProjectsRequest.retryConfig); - this.log(`✅ Backoff delay calculated: ${backoffDelay}ms`); - - // Test outbox pressure manager - const pressureManager = createDefaultOutboxPressureManager(); - const pressureStatus = await pressureManager.checkStoragePressure(50); - this.log('✅ Outbox pressure check:', pressureStatus); - - this.log('Generic Polling Interface test completed successfully'); - - } catch (error) { - this.log('Generic Polling Interface test failed:', error); - this.errorDisplay.showError(error as Error); - } - } - - private async testPollingSchedule(): Promise { - try { - this.log('📅 Testing Polling Schedule Configuration (iOS)...'); - - const timeSafariUser = this.configLoader.getTimeSafariUser(); - - // Create schedule configuration - const scheduleConfig: PollingScheduleConfig = { - request: { - endpoint: '/api/v2/report/plansLastUpdatedBetween', - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'User-Agent': 'TimeSafari-DailyNotificationPlugin/1.0.0', - 'Authorization': `Bearer ${await this.getJwtToken()}` - }, - body: { - planIds: timeSafariUser.starredPlanIds || [], - afterId: timeSafariUser.lastKnownPlanId, - limit: 100 - }, - responseSchema: { - validate: (data: unknown): data is StarredProjectsResponse => { - return data && Array.isArray(data.data); - }, - transformError: (error: unknown) => ({ - code: 'VALIDATION_ERROR', - message: error.message, - retryable: false - }) - }, - retryConfig: { - maxAttempts: 3, - backoffStrategy: 'exponential', - baseDelayMs: 1000 - }, - timeoutMs: 30000 - }, - schedule: { - cronExpression: '0 10,16 * * *', // 10 AM and 4 PM daily - timezone: 'UTC', - maxConcurrentPolls: 1 - }, - notificationConfig: { - enabled: true, - templates: { - singleUpdate: '{projectName} has been updated', - multipleUpdates: 'You have {count} new updates in your starred projects' - }, - groupingRules: { - maxGroupSize: 5, - timeWindowMinutes: 5 - } - }, - stateConfig: { - watermarkKey: 'lastAckedStarredPlanChangesJwtId', - storageAdapter: 'timesafari' - } - }; - - this.log('✅ Polling schedule configuration created successfully'); - this.log('Schedule details:', { - cronExpression: scheduleConfig.schedule.cronExpression, - timezone: scheduleConfig.schedule.timezone, - maxConcurrentPolls: scheduleConfig.schedule.maxConcurrentPolls, - watermarkKey: scheduleConfig.stateConfig.watermarkKey - }); - - // Mock scheduling the poll - this.log('📅 Scheduling polling (mock)...'); - const scheduleId = `ios-poll-${Date.now()}`; - this.log(`✅ Polling scheduled with ID: ${scheduleId}`); - - this.log('Polling Schedule test completed successfully'); - - } catch (error) { - this.log('Polling Schedule test failed:', error); - this.errorDisplay.showError(error as Error); - } - } - - private async testPollingResults(): Promise { - try { - this.log('📊 Testing Polling Results Handling (iOS)...'); - - // Mock polling result - const mockResult: PollingResult = { - success: true, - data: { - data: [ - { - planSummary: { - jwtId: '1704153600_mno345_87654321', - handleId: 'test-project-1', - name: 'Test Project 1', - issuerDid: 'did:example:test-issuer', - locLat: 40.7128, - locLon: -74.0060, - url: 'https://test-project-1.com', - version: '1.0.0' - }, - previousClaim: { - jwtId: '1704067200_abc123_12345678', - claimType: 'project_update', - claimData: { - status: 'in_progress', - progress: 0.75 - }, - metadata: { - createdAt: '2025-01-01T10:00:00Z', - updatedAt: '2025-01-01T12:00:00Z' - } - } - } - ], - hitLimit: false, - pagination: { - hasMore: false, - nextAfterId: null - } - }, - metadata: { - requestId: 'req-ios-test-123', - timestamp: new Date().toISOString(), - duration: 1250, - attempt: 1 - } - }; - - this.log('✅ Mock polling result created'); - this.log('Result details:', { - success: mockResult.success, - dataCount: mockResult.data?.data.length || 0, - hitLimit: mockResult.data?.hitLimit, - hasMore: mockResult.data?.pagination.hasMore, - duration: mockResult.metadata?.duration - }); - - // Test result processing - if (mockResult.success && mockResult.data) { - const changes = mockResult.data.data; - - if (changes.length > 0) { - this.log('📝 Processing polling results...'); - - // Generate notifications - this.log(`✅ Generated notifications for ${changes.length} changes`); - - // Update watermark with CAS - const latestJwtId = changes[changes.length - 1].planSummary.jwtId; - this.log(`✅ Updated watermark to: ${latestJwtId}`); - - // Acknowledge changes with server - const jwtIds = changes.map(c => c.planSummary.jwtId); - this.log(`✅ Acknowledged ${jwtIds.length} changes with server`); - } - } - - this.log('Polling Results test completed successfully'); - - } catch (error) { - this.log('Polling Results test failed:', error); - this.errorDisplay.showError(error as Error); - } - } - - private async getJwtToken(): Promise { - // Mock JWT token generation - return 'mock-jwt-token-ios-test'; - } - - // Static Daily Reminder Methods - private async scheduleDailyReminder(): Promise { - try { - this.log('Scheduling daily reminder...'); - - const reminderOptions = { - id: (document.getElementById('reminder-id') as HTMLInputElement)?.value || 'morning_checkin', - title: (document.getElementById('reminder-title') as HTMLInputElement)?.value || 'Good Morning!', - body: (document.getElementById('reminder-body') as HTMLInputElement)?.value || 'Time to check your TimeSafari community updates', - time: (document.getElementById('reminder-time') as HTMLInputElement)?.value || '09:00', - sound: (document.getElementById('reminder-sound') as HTMLInputElement)?.checked ?? true, - vibration: (document.getElementById('reminder-vibration') as HTMLInputElement)?.checked ?? true, - priority: (document.getElementById('reminder-priority') as HTMLSelectElement)?.value || 'normal', - repeatDaily: (document.getElementById('reminder-repeat') as HTMLInputElement)?.checked ?? true - }; - - this.log('Reminder options:', reminderOptions); - - await this.plugin.scheduleDailyReminder(reminderOptions); - this.log('✅ Daily reminder scheduled successfully'); - this.errorDisplay.showSuccess('Daily reminder scheduled successfully!'); - - } catch (error) { - this.log('❌ Failed to schedule daily reminder:', error); - this.errorDisplay.showError(error as Error); - } - } - - private async cancelDailyReminder(): Promise { - try { - this.log('Cancelling daily reminder...'); - - const reminderId = (document.getElementById('reminder-id') as HTMLInputElement)?.value || 'morning_checkin'; - - await this.plugin.cancelDailyReminder(reminderId); - this.log('✅ Daily reminder cancelled successfully'); - this.errorDisplay.showSuccess('Daily reminder cancelled successfully!'); - - } catch (error) { - this.log('❌ Failed to cancel daily reminder:', error); - this.errorDisplay.showError(error as Error); - } - } - - private async getScheduledReminders(): Promise { - try { - this.log('Getting scheduled reminders...'); - - const result = await this.plugin.getScheduledReminders(); - this.log('✅ Scheduled reminders retrieved:', result); - - if (result.reminders && result.reminders.length > 0) { - this.errorDisplay.showSuccess(`Found ${result.reminders.length} scheduled reminders`); - // eslint-disable-next-line no-console - console.table(result.reminders); - } else { - this.errorDisplay.showInfo('No scheduled reminders found'); - } - - } catch (error) { - this.log('❌ Failed to get scheduled reminders:', error); - this.errorDisplay.showError(error as Error); - } - } - - private async updateDailyReminder(): Promise { - try { - this.log('Updating daily reminder...'); - - const reminderId = (document.getElementById('reminder-id') as HTMLInputElement)?.value || 'morning_checkin'; - - const updateOptions = { - title: (document.getElementById('reminder-title') as HTMLInputElement)?.value, - body: (document.getElementById('reminder-body') as HTMLInputElement)?.value, - time: (document.getElementById('reminder-time') as HTMLInputElement)?.value, - sound: (document.getElementById('reminder-sound') as HTMLInputElement)?.checked, - vibration: (document.getElementById('reminder-vibration') as HTMLInputElement)?.checked, - priority: (document.getElementById('reminder-priority') as HTMLSelectElement)?.value, - repeatDaily: (document.getElementById('reminder-repeat') as HTMLInputElement)?.checked - }; - - this.log('Update options:', updateOptions); - - await this.plugin.updateDailyReminder(reminderId, updateOptions); - this.log('✅ Daily reminder updated successfully'); - this.errorDisplay.showSuccess('Daily reminder updated successfully!'); - - } catch (error) { - this.log('❌ Failed to update daily reminder:', error); - this.errorDisplay.showError(error as Error); - } - } -} - -// Initialize app when DOM is ready -document.addEventListener('DOMContentLoaded', () => { - new TimeSafariIOSTestApp(); -}); diff --git a/test-apps/ios-test/tsconfig.json b/test-apps/ios-test/tsconfig.json deleted file mode 100644 index aa6eba6..0000000 --- a/test-apps/ios-test/tsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "module": "ES2020", - "moduleResolution": "node", - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "outDir": "./dist", - "rootDir": "./src" - }, - "include": ["src/**/*"], - "exclude": ["node_modules", "dist"] -} diff --git a/test-apps/ios-test/webpack.config.js b/test-apps/ios-test/webpack.config.js deleted file mode 100644 index 4f64c73..0000000 --- a/test-apps/ios-test/webpack.config.js +++ /dev/null @@ -1,33 +0,0 @@ -const path = require('path'); -const HtmlWebpackPlugin = require('html-webpack-plugin'); - -module.exports = { - entry: './src/index.ts', - module: { - rules: [ - { - test: /\.ts$/, - use: 'ts-loader', - exclude: /node_modules/, - }, - ], - }, - resolve: { - extensions: ['.ts', '.js'], - }, - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist'), - clean: true, - }, - plugins: [ - new HtmlWebpackPlugin({ - template: './src/index.html', - }), - ], - devServer: { - static: './dist', - port: 3001, - hot: true, - }, -}; diff --git a/test-apps/launch-emulator-angle.sh b/test-apps/launch-emulator-angle.sh deleted file mode 100755 index 706d4ca..0000000 --- a/test-apps/launch-emulator-angle.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/bash - -# Android Emulator Launch Script - ANGLE Mode -# Uses ANGLE (Almost Native Graphics Layer Engine) for better NVIDIA compatibility -# Alternative to host GPU mode when experiencing binding issues -# Author: Matthew Raymer - -echo "🚀 Launching Android Emulator - ANGLE Mode..." - -# Check if emulator command exists -if ! command -v emulator &> /dev/null; then - echo "❌ Error: Android emulator not found!" - echo "Please install Android Studio and add emulator to PATH" - exit 1 -fi - -# Check if AVD exists -if ! emulator -list-avds | grep -q "TimeSafari_Emulator"; then - echo "❌ Error: TimeSafari_Emulator AVD not found!" - echo "Available AVDs:" - emulator -list-avds - exit 1 -fi - -echo "✅ Environment checks passed" -echo "🎮 Starting emulator with ANGLE rendering..." - -# Launch emulator with ANGLE and performance tuning -QT_QPA_PLATFORM=xcb \ -__NV_PRIME_RENDER_OFFLOAD=1 \ -__GLX_VENDOR_LIBRARY_NAME=nvidia \ -DRI_PRIME=1 \ -emulator -avd TimeSafari_Emulator \ - -gpu angle_indirect \ - -accel on \ - -cores 6 \ - -memory 4096 \ - -no-boot-anim \ - -no-snapshot-load \ - -feature -Bluetooth - -echo "🎯 Emulator launched with ANGLE rendering!" -echo "" -echo "📋 Configuration:" -echo " - ANGLE indirect rendering" -echo " - NVIDIA GPU offloading" -echo " - 6 CPU cores allocated" -echo " - 4GB RAM allocated" -echo " - Hardware acceleration enabled" -echo " - Fast startup (no boot animation)" -echo " - Clean state (no snapshot loading)" -echo " - Bluetooth disabled (prevents hangs)" -echo "" -echo "🔍 Benefits:" -echo " - Better NVIDIA compatibility on Linux" -echo " - Avoids mixed Vulkan+OpenGL binding issues" -echo " - More stable rendering pipeline" -echo " - Good fallback when host GPU mode fails" diff --git a/test-apps/launch-emulator-gpu.sh b/test-apps/launch-emulator-gpu.sh deleted file mode 100755 index 9649461..0000000 --- a/test-apps/launch-emulator-gpu.sh +++ /dev/null @@ -1,85 +0,0 @@ -#!/bin/bash - -# High-Performance Android Emulator Launch Script -# Optimized for Linux systems with NVIDIA graphics cards -# Author: Matthew Raymer - -echo "🚀 Launching Android Emulator with GPU Acceleration..." - -# Check if emulator command exists -if ! command -v emulator &> /dev/null; then - echo "❌ Error: Android emulator not found!" - echo "Please install Android Studio and add emulator to PATH" - echo "export PATH=\$PATH:\$ANDROID_HOME/emulator" - exit 1 -fi - -# Check if AVD exists -if ! emulator -list-avds | grep -q "TimeSafari_Emulator"; then - echo "❌ Error: TimeSafari_Emulator AVD not found!" - echo "Available AVDs:" - emulator -list-avds - echo "" - echo "Please create TimeSafari_Emulator AVD or modify this script" - exit 1 -fi - -# Check if NVIDIA drivers are available -if ! ls /usr/share/vulkan/icd.d/nvidia_icd.json &> /dev/null; then - echo "⚠️ Warning: NVIDIA Vulkan ICD not found" - echo "GPU acceleration may not work optimally" - echo "Consider installing NVIDIA drivers with Vulkan support" -fi - -echo "✅ Environment checks passed" -echo "🎮 Starting emulator with GPU acceleration..." - -# Launch emulator with GPU acceleration, network fixes, and performance tuning -QT_QPA_PLATFORM=xcb \ -__NV_PRIME_RENDER_OFFLOAD=1 \ -__GLX_VENDOR_LIBRARY_NAME=nvidia \ -__VK_LAYER_NV_optimus=NVIDIA_only \ -VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/nvidia_icd.json \ -DRI_PRIME=1 \ -emulator -avd TimeSafari_Emulator \ - -gpu host \ - -feature Vulkan \ - -accel on \ - -cores 6 \ - -memory 4096 \ - -no-boot-anim \ - -no-snapshot-load \ - -dns-server 8.8.8.8,1.1.1.1 \ - -feature -Bluetooth - -echo "🎯 Emulator launched with GPU acceleration!" -echo "" -echo "📋 Performance Features Enabled:" -echo " - Hardware GPU acceleration" -echo " - Vulkan graphics API support" -echo " - NVIDIA GPU offloading" -echo " - 6 CPU cores allocated" -echo " - 4GB RAM allocated" -echo " - Fast startup (no boot animation)" -echo " - Clean state (no snapshot loading)" -echo " - Fixed DNS servers (8.8.8.8, 1.1.1.1)" -echo " - Bluetooth disabled (prevents hangs)" -echo "" -echo "🔧 Troubleshooting:" -echo " - If emulator is slow, check NVIDIA drivers" -echo " - For Intel/AMD graphics, remove NVIDIA-specific variables" -echo " - Monitor GPU usage with: nvidia-smi" -echo "" -echo "🔍 GPU Binding Issues:" -echo " If OpenGL still binds to Intel iGPU instead of NVIDIA:" -echo " 1. Check emulator banner for 'OpenGL Vendor=Google (NVIDIA)'" -echo " 2. Try alternative GPU modes:" -echo " - Pure OpenGL: Remove -feature Vulkan flag" -echo " - ANGLE path: Use -gpu angle_indirect" -echo " - Mesa fallback: Use -gpu mesa" -echo " 3. Verify dGPU usage: nvidia-smi dmon -s u" -echo "" -echo "📋 Performance Verification:" -echo " - Monitor GPU utilization: watch -n1 'nvidia-smi --query-compute-apps=pid,process_name,used_memory --format=csv,noheader | grep qemu'" -echo " - Check ADB connection: adb kill-server && adb start-server" -echo " - Clean snapshots: Delete ~/.android/avd/TimeSafari_Emulator.avd/snapshots/" diff --git a/test-apps/launch-emulator-help.sh b/test-apps/launch-emulator-help.sh deleted file mode 100755 index b5aa6e6..0000000 --- a/test-apps/launch-emulator-help.sh +++ /dev/null @@ -1,106 +0,0 @@ -#!/bin/bash - -# Android Emulator Launch Options Helper -# Lists all available launch scripts and their purposes -# Author: Matthew Raymer - -echo "🚀 Android Emulator Launch Options" -echo "==================================" -echo "" - -echo "📋 Available Launch Scripts:" -echo "" - -echo "1. 🎮 GPU Accelerated (Recommended)" -echo " ./launch-emulator-gpu.sh" -echo " - Full NVIDIA GPU acceleration with Vulkan" -echo " - Best performance for development" -echo " - Use when GPU binding works correctly" -echo "" - -echo "2. 🔧 Pure OpenGL Mode" -echo " ./launch-emulator-opengl.sh" -echo " - Pure OpenGL rendering (no Vulkan)" -echo " - Use when Vulkan+OpenGL mixed mode binds to Intel iGPU" -echo " - Good fallback for GPU binding issues" -echo "" - -echo "3. ⚡ ANGLE Mode" -echo " ./launch-emulator-angle.sh" -echo " - ANGLE (Almost Native Graphics Layer Engine)" -echo " - Better NVIDIA compatibility on Linux" -echo " - More stable rendering pipeline" -echo "" - -echo "4. 🛡️ Mesa Fallback" -echo " ./launch-emulator-mesa.sh" -echo " - Software rendering as last resort" -echo " - Use for stability testing" -echo " - More CPU intensive but very stable" -echo "" - -echo "5. 🌐 Network Fix Mode" -echo " ./launch-emulator-network-fix.sh" -echo " - Fixes DNS/network connectivity issues" -echo " - Resolves Play Services ANRs and timeouts" -echo " - Clean state with explicit DNS servers" -echo "" - -echo "6. 🔍 Network Verification" -echo " ./verify-emulator-network.sh" -echo " - Diagnoses network connectivity problems" -echo " - Tests DNS resolution and internet access" -echo " - Identifies root cause of ANRs" -echo "" - -echo "7. ⚡ Maximum Performance Mode" -echo " ./launch-emulator-max-performance.sh" -echo " - All performance optimizations enabled" -echo " - 8 CPU cores, 6GB RAM allocated" -echo " - Disabled unnecessary features" -echo " - Use only on high-end systems (16GB+ RAM)" -echo "" - -echo "🔍 Troubleshooting:" -echo "" - -echo "If experiencing ANRs and Play Services failures:" -echo "1. Run network verification: ./verify-emulator-network.sh" -echo "2. Try network fix mode: ./launch-emulator-network-fix.sh" -echo "3. Clear Play Services cache if needed" -echo "4. Check VPN/firewall settings on host" -echo "" - -echo "If emulator feels sluggish or GPU utilization is low:" -echo "1. Check emulator banner for 'OpenGL Vendor=Google (NVIDIA)'" -echo "2. Monitor GPU usage: nvidia-smi dmon -s u" -echo "3. Try different GPU modes in order: GPU → OpenGL → ANGLE → Mesa" -echo "4. See EMULATOR_TROUBLESHOOTING.md for detailed solutions" -echo "" - -echo "📊 Performance Expectations:" -echo "" -echo "Hardware Acceleration (NVIDIA):" -echo " - GPU Utilization: 20-60%" -echo " - UI Responsiveness: Smooth, 60fps" -echo " - Startup Time: 30-60 seconds" -echo "" -echo "Software Rendering (Mesa):" -echo " - CPU Usage: 50-80%" -echo " - UI Responsiveness: Slower, 30fps" -echo " - Startup Time: 60-120 seconds" -echo "" - -echo "📚 Documentation:" -echo " - SETUP_GUIDE.md - Complete setup instructions" -echo " - EMULATOR_TROUBLESHOOTING.md - GPU binding solutions" -echo " - README.md - Project overview and quick start" -echo "" - -echo "🎯 Quick Start:" -echo " 1. If ANRs/Play Services issues: ./verify-emulator-network.sh" -echo " 2. If network issues: ./launch-emulator-network-fix.sh" -echo " 3. For GPU issues: ./launch-emulator-gpu.sh" -echo " 4. If GPU binding issues: ./launch-emulator-opengl.sh" -echo " 5. For maximum performance: ./launch-emulator-max-performance.sh" -echo " 6. Last resort: ./launch-emulator-mesa.sh" diff --git a/test-apps/launch-emulator-max-performance.sh b/test-apps/launch-emulator-max-performance.sh deleted file mode 100755 index 8e184e9..0000000 --- a/test-apps/launch-emulator-max-performance.sh +++ /dev/null @@ -1,77 +0,0 @@ -#!/bin/bash - -# Android Emulator Launch Script - High Performance Mode -# Maximum performance with all optimizations enabled -# Author: Matthew Raymer - -echo "🚀 Launching Android Emulator - High Performance Mode..." - -# Check if emulator command exists -if ! command -v emulator &> /dev/null; then - echo "❌ Error: Android emulator not found!" - echo "Please install Android Studio and add emulator to PATH" - exit 1 -fi - -# Check if AVD exists -if ! emulator -list-avds | grep -q "TimeSafari_Emulator"; then - echo "❌ Error: TimeSafari_Emulator AVD not found!" - echo "Available AVDs:" - emulator -list-avds - exit 1 -fi - -# Check if NVIDIA drivers are available -if ! ls /usr/share/vulkan/icd.d/nvidia_icd.json &> /dev/null; then - echo "⚠️ Warning: NVIDIA Vulkan ICD not found" - echo "GPU acceleration may not work optimally" -fi - -echo "✅ Environment checks passed" -echo "🎮 Starting emulator with maximum performance..." - -# Launch emulator with all performance optimizations -QT_QPA_PLATFORM=xcb \ -__NV_PRIME_RENDER_OFFLOAD=1 \ -__GLX_VENDOR_LIBRARY_NAME=nvidia \ -__VK_LAYER_NV_optimus=NVIDIA_only \ -VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/nvidia_icd.json \ -DRI_PRIME=1 \ -emulator -avd TimeSafari_Emulator \ - -gpu host \ - -feature Vulkan \ - -accel on \ - -cores 8 \ - -memory 6144 \ - -no-boot-anim \ - -no-snapshot-load \ - -dns-server 8.8.8.8,1.1.1.1 \ - -feature -Bluetooth \ - -camera-back none \ - -camera-front none \ - -no-audio - -echo "🎯 Emulator launched with maximum performance!" -echo "" -echo "📋 High Performance Features:" -echo " - Hardware GPU acceleration with Vulkan" -echo " - NVIDIA GPU offloading" -echo " - 8 CPU cores allocated (maximum)" -echo " - 6GB RAM allocated (high memory)" -echo " - Fast startup (no boot animation)" -echo " - Clean state (no snapshot loading)" -echo " - Fixed DNS servers (8.8.8.8, 1.1.1.1)" -echo " - Disabled unnecessary features:" -echo " - Bluetooth disabled" -echo " - Cameras disabled" -echo " - Audio disabled" -echo "" -echo "🔍 Performance Monitoring:" -echo " - GPU usage: nvidia-smi dmon -s u" -echo " - CPU usage: htop" -echo " - Memory usage: free -h" -echo "" -echo "⚠️ Note: This configuration uses maximum resources" -echo " - Ensure your system has sufficient RAM (16GB+ recommended)" -echo " - Monitor system performance during use" -echo " - Adjust -cores and -memory if system becomes unresponsive" diff --git a/test-apps/launch-emulator-mesa.sh b/test-apps/launch-emulator-mesa.sh deleted file mode 100755 index 1318685..0000000 --- a/test-apps/launch-emulator-mesa.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/bash - -# Android Emulator Launch Script - Mesa Fallback Mode -# Uses Mesa software rendering as last resort for stability -# Use when hardware acceleration causes issues -# Author: Matthew Raymer - -echo "🚀 Launching Android Emulator - Mesa Fallback Mode..." - -# Check if emulator command exists -if ! command -v emulator &> /dev/null; then - echo "❌ Error: Android emulator not found!" - echo "Please install Android Studio and add emulator to PATH" - exit 1 -fi - -# Check if AVD exists -if ! emulator -list-avds | grep -q "TimeSafari_Emulator"; then - echo "❌ Error: TimeSafari_Emulator AVD not found!" - echo "Available AVDs:" - emulator -list-avds - exit 1 -fi - -echo "✅ Environment checks passed" -echo "🎮 Starting emulator with Mesa software rendering..." - -# Launch emulator with Mesa software rendering -emulator -avd TimeSafari_Emulator \ - -gpu mesa \ - -no-boot-anim \ - -no-snapshot-load \ - -feature -Bluetooth - -echo "🎯 Emulator launched with Mesa software rendering!" -echo "" -echo "📋 Configuration:" -echo " - Mesa software rendering" -echo " - No hardware acceleration" -echo " - Fast startup (no boot animation)" -echo " - Clean state (no snapshot loading)" -echo " - Bluetooth disabled (prevents hangs)" -echo "" -echo "⚠️ Performance Notes:" -echo " - Slower than hardware acceleration" -echo " - More CPU intensive" -echo " - Use only for stability testing" -echo " - Good for debugging GPU issues" -echo "" -echo "🔄 To return to hardware acceleration:" -echo " - Use ./launch-emulator-gpu.sh for NVIDIA GPU" -echo " - Use ./launch-emulator-opengl.sh for Pure OpenGL" -echo " - Use ./launch-emulator-angle.sh for ANGLE mode" diff --git a/test-apps/launch-emulator-network-fix.sh b/test-apps/launch-emulator-network-fix.sh deleted file mode 100755 index cb2c3d5..0000000 --- a/test-apps/launch-emulator-network-fix.sh +++ /dev/null @@ -1,62 +0,0 @@ -#!/bin/bash - -# Android Emulator Launch Script - Network Fix Mode -# Addresses DNS/network connectivity issues that cause ANRs and Play Services failures -# Author: Matthew Raymer - -echo "🚀 Launching Android Emulator - Network Fix Mode..." - -# Check if emulator command exists -if ! command -v emulator &> /dev/null; then - echo "❌ Error: Android emulator not found!" - echo "Please install Android Studio and add emulator to PATH" - exit 1 -fi - -# Check if AVD exists -if ! emulator -list-avds | grep -q "TimeSafari_Emulator"; then - echo "❌ Error: TimeSafari_Emulator AVD not found!" - echo "Available AVDs:" - emulator -list-avds - exit 1 -fi - -echo "✅ Environment checks passed" -echo "🌐 Starting emulator with network fixes..." - -# Launch emulator with network fixes, performance tuning, and clean state -QT_QPA_PLATFORM=xcb \ -emulator -avd TimeSafari_Emulator \ - -gpu host \ - -accel on \ - -cores 6 \ - -memory 4096 \ - -no-boot-anim \ - -no-snapshot-load \ - -wipe-data \ - -dns-server 8.8.8.8,1.1.1.1 \ - -feature -Bluetooth - -echo "🎯 Emulator launched with network fixes!" -echo "" -echo "📋 Network Fixes Applied:" -echo " - Explicit DNS servers (8.8.8.8, 1.1.1.1)" -echo " - Clean state (wipe-data)" -echo " - No snapshot loading" -echo " - 6 CPU cores allocated" -echo " - 4GB RAM allocated" -echo " - Fast startup (no boot animation)" -echo " - Bluetooth disabled (prevents hangs)" -echo "" -echo "🔍 Network Verification Commands:" -echo " # Check airplane mode" -echo " adb -e shell settings get global airplane_mode_on" -echo "" -echo " # Check network interfaces" -echo " adb -e shell ip addr; adb -e shell ip route" -echo "" -echo " # Test DNS resolution" -echo " adb -e shell ping -c1 8.8.8.8" -echo " adb -e shell ping -c1 connectivitycheck.gstatic.com" -echo "" -echo "⚠️ Note: This will wipe emulator data for clean network state" diff --git a/test-apps/launch-emulator-opengl.sh b/test-apps/launch-emulator-opengl.sh deleted file mode 100755 index fd07252..0000000 --- a/test-apps/launch-emulator-opengl.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/bash - -# Android Emulator Launch Script - Pure OpenGL Mode -# Forces OpenGL rendering on NVIDIA GPU (no Vulkan) -# Use when Vulkan+OpenGL mixed mode binds to Intel iGPU -# Author: Matthew Raymer - -echo "🚀 Launching Android Emulator - Pure OpenGL Mode..." - -# Check if emulator command exists -if ! command -v emulator &> /dev/null; then - echo "❌ Error: Android emulator not found!" - echo "Please install Android Studio and add emulator to PATH" - exit 1 -fi - -# Check if AVD exists -if ! emulator -list-avds | grep -q "TimeSafari_Emulator"; then - echo "❌ Error: TimeSafari_Emulator AVD not found!" - echo "Available AVDs:" - emulator -list-avds - exit 1 -fi - -echo "✅ Environment checks passed" -echo "🎮 Starting emulator with Pure OpenGL rendering..." - -# Launch emulator with Pure OpenGL and performance tuning -QT_QPA_PLATFORM=xcb \ -__NV_PRIME_RENDER_OFFLOAD=1 \ -__GLX_VENDOR_LIBRARY_NAME=nvidia \ -DRI_PRIME=1 \ -emulator -avd TimeSafari_Emulator \ - -gpu host \ - -accel on \ - -cores 6 \ - -memory 4096 \ - -no-boot-anim \ - -no-snapshot-load \ - -feature -Bluetooth - -echo "🎯 Emulator launched with Pure OpenGL rendering!" -echo "" -echo "📋 Configuration:" -echo " - Pure OpenGL rendering (no Vulkan)" -echo " - NVIDIA GPU offloading" -echo " - 6 CPU cores allocated" -echo " - 4GB RAM allocated" -echo " - Hardware acceleration enabled" -echo " - Fast startup (no boot animation)" -echo " - Clean state (no snapshot loading)" -echo " - Bluetooth disabled (prevents hangs)" -echo "" -echo "🔍 Verification:" -echo " - Check banner for 'OpenGL Vendor=Google (NVIDIA)'" -echo " - Monitor GPU: nvidia-smi dmon -s u" -echo " - Should avoid Intel iGPU binding issues" diff --git a/test-apps/setup-android.sh b/test-apps/setup-android.sh deleted file mode 100755 index 2d14829..0000000 --- a/test-apps/setup-android.sh +++ /dev/null @@ -1,123 +0,0 @@ -#!/bin/bash - -# Android Test App Setup Script -echo "🚀 Setting up Android Test App..." - -# Check if we're in the right directory -if [ ! -d "android-test" ]; then - echo "❌ Error: android-test directory not found!" - echo "Please run this script from the test-apps directory" - exit 1 -fi - -cd android-test - -# Check Node.js version -echo "🔍 Checking Node.js version..." -node_version=$(node --version 2>/dev/null) -if [ $? -ne 0 ]; then - echo "❌ Error: Node.js not found!" - echo "Please install Node.js 18+ from https://nodejs.org/" - exit 1 -fi -echo "✅ Node.js version: $node_version" - -# Install dependencies -echo "📦 Installing dependencies..." -npm install -if [ $? -ne 0 ]; then - echo "❌ Error: Failed to install dependencies!" - exit 1 -fi - -# Install Capacitor CLI globally if not present -if ! command -v cap &> /dev/null; then - echo "🔧 Installing Capacitor CLI globally..." - npm install -g @capacitor/cli - if [ $? -ne 0 ]; then - echo "❌ Error: Failed to install Capacitor CLI!" - exit 1 - fi -else - echo "✅ Capacitor CLI already installed" -fi - -# Initialize Capacitor (only if not already initialized) -if [ ! -f "capacitor.config.ts" ]; then - echo "⚡ Initializing Capacitor..." - npx cap init "Daily Notification Android Test" "com.timesafari.dailynotification.androidtest" - if [ $? -ne 0 ]; then - echo "❌ Error: Failed to initialize Capacitor!" - exit 1 - fi -else - echo "✅ Capacitor already initialized" -fi - -# Add Android platform (only if not already added) -if [ ! -d "android" ]; then - echo "📱 Adding Android platform..." - npx cap add android - if [ $? -ne 0 ]; then - echo "❌ Error: Failed to add Android platform!" - echo "Make sure Android Studio and Android SDK are installed" - exit 1 - fi -else - echo "✅ Android platform already added" -fi - -# Build web assets -echo "🔨 Building web assets..." -npm run build -if [ $? -ne 0 ]; then - echo "❌ Error: Failed to build web assets!" - exit 1 -fi - -# Sync to native -echo "🔄 Syncing to native..." -npx cap sync android -if [ $? -ne 0 ]; then - echo "❌ Error: Failed to sync to native!" - echo "🔧 Attempting to fix Gradle sync issues..." - - # Fix common Gradle sync issues - cd android - ./gradlew clean - ./gradlew --stop - - # Clear Gradle cache if needed - if [ -d ~/.gradle/wrapper/dists/gradle-9.0-milestone-1* ]; then - echo "🧹 Clearing incompatible Gradle cache..." - rm -rf ~/.gradle/wrapper/dists/gradle-9.0-milestone-1* - fi - - cd .. - - # Try sync again - echo "🔄 Retrying sync..." - npx cap sync android - if [ $? -ne 0 ]; then - echo "❌ Error: Sync still failing after cleanup" - echo "📋 See GRADLE_TROUBLESHOOTING.md for manual fixes" - exit 1 - fi -fi - -echo "" -echo "✅ Android test app setup complete!" -echo "" -echo "📋 Prerequisites check:" -echo "- Android Studio installed: $(command -v studio &> /dev/null && echo '✅' || echo '❌')" -echo "- Android SDK configured: $(echo $ANDROID_HOME | grep -q . && echo '✅' || echo '❌')" -echo "" -echo "🚀 Next steps:" -echo "1. Open Android Studio: npx cap open android" -echo "2. Run on device/emulator: npx cap run android" -echo "3. Or test web version: npm run dev" -echo "" -echo "🔧 Troubleshooting:" -echo "- If Android Studio doesn't open, install it from https://developer.android.com/studio" -echo "- If sync fails, check Android SDK installation" -echo "- For web testing, run: npm run dev" diff --git a/test-apps/setup-electron.sh b/test-apps/setup-electron.sh deleted file mode 100755 index 4b7a9f7..0000000 --- a/test-apps/setup-electron.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash - -# Electron Test App Setup Script -echo "🚀 Setting up Electron Test App..." - -# Check if we're in the right directory -if [ ! -d "electron-test" ]; then - echo "❌ Error: electron-test directory not found!" - echo "Please run this script from the test-apps directory" - exit 1 -fi - -cd electron-test - -# Check Node.js version -echo "🔍 Checking Node.js version..." -node_version=$(node --version 2>/dev/null) -if [ $? -ne 0 ]; then - echo "❌ Error: Node.js not found!" - echo "Please install Node.js 18+ from https://nodejs.org/" - exit 1 -fi -echo "✅ Node.js version: $node_version" - -# Install dependencies -echo "📦 Installing dependencies..." -npm install -if [ $? -ne 0 ]; then - echo "❌ Error: Failed to install dependencies!" - exit 1 -fi - -# Build web assets -echo "🔨 Building web assets..." -npm run build-web -if [ $? -ne 0 ]; then - echo "❌ Error: Failed to build web assets!" - exit 1 -fi - -echo "" -echo "✅ Electron test app setup complete!" -echo "" -echo "📋 Prerequisites check:" -echo "- Node.js installed: ✅" -echo "- Electron dependencies: ✅" -echo "" -echo "🚀 Next steps:" -echo "1. Run Electron app: npm start" -echo "2. Run in dev mode: npm run dev" -echo "3. Build and run: npm run electron" -echo "" -echo "🔧 Troubleshooting:" -echo "- If Electron doesn't start, check Node.js version (18+)" -echo "- For development, use: npm run dev" -echo "- Check console logs for detailed error information" diff --git a/test-apps/setup-ios.sh b/test-apps/setup-ios.sh deleted file mode 100755 index f603782..0000000 --- a/test-apps/setup-ios.sh +++ /dev/null @@ -1,101 +0,0 @@ -#!/bin/bash - -# iOS Test App Setup Script -echo "🚀 Setting up iOS Test App..." - -# Check if we're in the right directory -if [ ! -d "ios-test" ]; then - echo "❌ Error: ios-test directory not found!" - echo "Please run this script from the test-apps directory" - exit 1 -fi - -cd ios-test - -# Check Node.js version -echo "🔍 Checking Node.js version..." -node_version=$(node --version 2>/dev/null) -if [ $? -ne 0 ]; then - echo "❌ Error: Node.js not found!" - echo "Please install Node.js 18+ from https://nodejs.org/" - exit 1 -fi -echo "✅ Node.js version: $node_version" - -# Install dependencies -echo "📦 Installing dependencies..." -npm install -if [ $? -ne 0 ]; then - echo "❌ Error: Failed to install dependencies!" - exit 1 -fi - -# Install Capacitor CLI globally if not present -if ! command -v cap &> /dev/null; then - echo "🔧 Installing Capacitor CLI globally..." - npm install -g @capacitor/cli - if [ $? -ne 0 ]; then - echo "❌ Error: Failed to install Capacitor CLI!" - exit 1 - fi -else - echo "✅ Capacitor CLI already installed" -fi - -# Initialize Capacitor (only if not already initialized) -if [ ! -f "capacitor.config.ts" ]; then - echo "⚡ Initializing Capacitor..." - npx cap init "Daily Notification iOS Test" "com.timesafari.dailynotification.iostest" - if [ $? -ne 0 ]; then - echo "❌ Error: Failed to initialize Capacitor!" - exit 1 - fi -else - echo "✅ Capacitor already initialized" -fi - -# Add iOS platform (only if not already added) -if [ ! -d "ios" ]; then - echo "🍎 Adding iOS platform..." - npx cap add ios - if [ $? -ne 0 ]; then - echo "❌ Error: Failed to add iOS platform!" - echo "Make sure Xcode and iOS SDK are installed" - exit 1 - fi -else - echo "✅ iOS platform already added" -fi - -# Build web assets -echo "🔨 Building web assets..." -npm run build -if [ $? -ne 0 ]; then - echo "❌ Error: Failed to build web assets!" - exit 1 -fi - -# Sync to native -echo "🔄 Syncing to native..." -npx cap sync ios -if [ $? -ne 0 ]; then - echo "❌ Error: Failed to sync to native!" - exit 1 -fi - -echo "" -echo "✅ iOS test app setup complete!" -echo "" -echo "📋 Prerequisites check:" -echo "- Xcode installed: $(command -v xcodebuild &> /dev/null && echo '✅' || echo '❌')" -echo "- iOS Simulator available: $(xcrun simctl list devices &> /dev/null && echo '✅' || echo '❌')" -echo "" -echo "🚀 Next steps:" -echo "1. Open Xcode: npx cap open ios" -echo "2. Run on device/simulator: npx cap run ios" -echo "3. Or test web version: npm run dev" -echo "" -echo "🔧 Troubleshooting:" -echo "- If Xcode doesn't open, install it from the Mac App Store" -echo "- If sync fails, check Xcode command line tools: xcode-select --install" -echo "- For web testing, run: npm run dev" diff --git a/test-apps/shared/config-loader.ts b/test-apps/shared/config-loader.ts deleted file mode 100644 index b3ba1bf..0000000 --- a/test-apps/shared/config-loader.ts +++ /dev/null @@ -1,552 +0,0 @@ -/** - * Configuration loader for TimeSafari test apps - * - * Loads configuration from JSON files and provides typed access - * to TimeSafari-specific settings, Endorser.ch API endpoints, - * and test data. - * - * @author Matthew Raymer - * @version 1.0.0 - */ - -export interface TimeSafariConfig { - timesafari: { - appId: string; - appName: string; - version: string; - description: string; - }; - endorser: { - baseUrl: string; - apiVersion: string; - endpoints: { - offers: string; - offersToPlans: string; - plansLastUpdated: string; - notificationsBundle: string; - }; - authentication: { - type: string; - token: string; - headers: Record; - }; - pagination: { - defaultLimit: number; - maxLimit: number; - hitLimitThreshold: number; - }; - }; - notificationTypes: { - offers: { - enabled: boolean; - types: string[]; - }; - projects: { - enabled: boolean; - types: string[]; - }; - people: { - enabled: boolean; - types: string[]; - }; - items: { - enabled: boolean; - types: string[]; - }; - }; - scheduling: { - contentFetch: { - schedule: string; - time: string; - description: string; - }; - userNotification: { - schedule: string; - time: string; - description: string; - }; - }; - testData: { - userDid: string; - starredPlanIds: string[]; - lastKnownOfferId: string; - lastKnownPlanId: string; - mockOffers: Record[]; - mockProjects: Record[]; - }; - callbacks: { - offers: { - enabled: boolean; - localHandler: string; - }; - projects: { - enabled: boolean; - localHandler: string; - }; - people: { - enabled: boolean; - localHandler: string; - }; - items: { - enabled: boolean; - localHandler: string; - }; - communityAnalytics: { - enabled: boolean; - endpoint: string; - headers: Record; - }; - }; - observability: { - enableLogging: boolean; - logLevel: string; - enableMetrics: boolean; - enableHealthChecks: boolean; - }; -} - -/** - * Configuration loader class - */ -export class ConfigLoader { - private static instance: ConfigLoader; - private config: TimeSafariConfig | null = null; - - private constructor() { - // Private constructor for singleton pattern - } - - /** - * Get singleton instance - */ - public static getInstance(): ConfigLoader { - if (!ConfigLoader.instance) { - ConfigLoader.instance = new ConfigLoader(); - } - return ConfigLoader.instance; - } - - /** - * Load configuration from JSON file - */ - public async loadConfig(): Promise { - if (this.config) { - return this.config; - } - - try { - // In a real app, this would fetch from a config file - // For test apps, we'll use a hardcoded config - this.config = { - timesafari: { - appId: "app.timesafari.test", - appName: "TimeSafari Test", - version: "1.0.0", - description: "Test app for TimeSafari Daily Notification Plugin integration" - }, - endorser: { - baseUrl: "http://localhost:3001", - apiVersion: "v2", - endpoints: { - offers: "/api/v2/report/offers", - offersToPlans: "/api/v2/report/offersToPlansOwnedByMe", - plansLastUpdated: "/api/v2/report/plansLastUpdatedBetween", - notificationsBundle: "/api/v2/report/notifications/bundle" - }, - authentication: { - type: "Bearer", - token: "test-jwt-token-12345", - headers: { - "Authorization": "Bearer test-jwt-token-12345", - "Content-Type": "application/json", - "X-Privacy-Level": "user-controlled" - } - }, - pagination: { - defaultLimit: 50, - maxLimit: 100, - hitLimitThreshold: 50 - } - }, - notificationTypes: { - offers: { - enabled: true, - types: [ - "new_to_me", - "changed_to_me", - "new_to_projects", - "changed_to_projects", - "new_to_favorites", - "changed_to_favorites" - ] - }, - projects: { - enabled: true, - types: [ - "local_new", - "local_changed", - "content_interest_new", - "favorited_changed" - ] - }, - people: { - enabled: true, - types: [ - "local_new", - "local_changed", - "content_interest_new", - "favorited_changed", - "contacts_changed" - ] - }, - items: { - enabled: true, - types: [ - "local_new", - "local_changed", - "favorited_changed" - ] - } - }, - scheduling: { - contentFetch: { - schedule: "0 8 * * *", - time: "08:00", - description: "8 AM daily - fetch community updates" - }, - userNotification: { - schedule: "0 9 * * *", - time: "09:00", - description: "9 AM daily - notify users of community updates" - } - }, - testData: { - userDid: "did:example:testuser123", - starredPlanIds: [ - "plan-community-garden", - "plan-local-food", - "plan-sustainability" - ], - lastKnownOfferId: "01HSE3R9MAC0FT3P3KZ382TWV7", - lastKnownPlanId: "01HSE3R9MAC0FT3P3KZ382TWV8", - mockOffers: [ - { - jwtId: "01HSE3R9MAC0FT3P3KZ382TWV7", - handleId: "offer-web-dev-001", - offeredByDid: "did:example:offerer123", - recipientDid: "did:example:testuser123", - objectDescription: "Web development services for community project", - unit: "USD", - amount: 1000, - amountGiven: 500, - amountGivenConfirmed: 250 - } - ], - mockProjects: [ - { - plan: { - jwtId: "01HSE3R9MAC0FT3P3KZ382TWV8", - handleId: "plan-community-garden", - name: "Community Garden Project", - description: "Building a community garden for local food production", - issuerDid: "did:example:issuer123", - agentDid: "did:example:agent123" - }, - wrappedClaimBefore: null - } - ] - }, - callbacks: { - offers: { - enabled: true, - localHandler: "handleOffersNotification" - }, - projects: { - enabled: true, - localHandler: "handleProjectsNotification" - }, - people: { - enabled: true, - localHandler: "handlePeopleNotification" - }, - items: { - enabled: true, - localHandler: "handleItemsNotification" - }, - communityAnalytics: { - enabled: true, - endpoint: "http://localhost:3001/api/analytics/community-events", - headers: { - "Content-Type": "application/json", - "X-Privacy-Level": "aggregated" - } - } - }, - observability: { - enableLogging: true, - logLevel: "debug", - enableMetrics: true, - enableHealthChecks: true - } - }; - - return this.config; - } catch (error) { - console.error('Failed to load configuration:', error); - throw error; - } - } - - /** - * Get configuration - */ - public getConfig(): TimeSafariConfig { - if (!this.config) { - throw new Error('Configuration not loaded. Call loadConfig() first.'); - } - return this.config; - } - - /** - * Get Endorser.ch API URL for a specific endpoint - */ - public getEndorserUrl(endpoint: keyof TimeSafariConfig['endorser']['endpoints']): string { - const config = this.getConfig(); - return `${config.endorser.baseUrl}${config.endorser.endpoints[endpoint]}`; - } - - /** - * Get authentication headers - */ - public getAuthHeaders(): Record { - const config = this.getConfig(); - return config.endorser.authentication.headers; - } - - /** - * Get test data - */ - public getTestData(): Record { - const config = this.getConfig(); - return config.testData; - } - - /** - * Get notification types for a specific category - */ - public getNotificationTypes(category: keyof TimeSafariConfig['notificationTypes']): Record { - const config = this.getConfig(); - return config.notificationTypes[category]; - } -} - -/** - * Logger utility for test apps - */ -export class TestLogger { - private logLevel: string; - private logs: string[] = []; - - constructor(logLevel = 'debug') { - this.logLevel = logLevel; - } - - private shouldLog(level: string): boolean { - const levels = ['error', 'warn', 'info', 'debug']; - return levels.indexOf(level) <= levels.indexOf(this.logLevel); - } - - private addToLogs(level: string, message: string, _data?: Record): void { - const timestamp = new Date().toISOString(); - const logEntry = `[${timestamp}] [${level.toUpperCase()}] ${message}`; - this.logs.push(logEntry); - - // Keep only last 1000 logs to prevent memory issues - if (this.logs.length > 1000) { - this.logs = this.logs.slice(-1000); - } - } - - public debug(message: string, data?: Record): void { - if (this.shouldLog('debug')) { - // console.log(`[DEBUG] ${message}`, data || ''); - this.addToLogs('debug', message, data); - } - } - - public info(message: string, data?: Record): void { - if (this.shouldLog('info')) { - // console.log(`[INFO] ${message}`, data || ''); - this.addToLogs('info', message, data); - } - } - - public warn(message: string, data?: Record): void { - if (this.shouldLog('warn')) { - // console.warn(`[WARN] ${message}`, data || ''); - this.addToLogs('warn', message, data); - } - } - - public error(message: string, data?: Record): void { - if (this.shouldLog('error')) { - // console.error(`[ERROR] ${message}`, data || ''); - this.addToLogs('error', message, data); - } - } - - public getLogs(): string[] { - return [...this.logs]; - } - - public clearLogs(): void { - this.logs = []; - } - - public exportLogs(): string { - return this.logs.join('\n'); - } -} - -/** - * Mock DailyNotificationService for test apps - */ -export class MockDailyNotificationService { - private config: TimeSafariConfig; - private logger: TestLogger; - private isInitialized = false; - - constructor(config: TimeSafariConfig) { - this.config = config; - this.logger = new TestLogger(config.observability.logLevel); - } - - /** - * Initialize the service - */ - public async initialize(): Promise { - this.logger.info('Initializing Mock DailyNotificationService'); - this.isInitialized = true; - this.logger.info('Mock DailyNotificationService initialized successfully'); - } - - /** - * Schedule dual notification (content fetch + user notification) - */ - public async scheduleDualNotification(config: Record): Promise { - if (!this.isInitialized) { - throw new Error('Service not initialized'); - } - - this.logger.info('Scheduling dual notification', config); - - // Simulate content fetch - if (config.contentFetch?.enabled) { - await this.simulateContentFetch(config.contentFetch); - } - - // Simulate user notification - if (config.userNotification?.enabled) { - await this.simulateUserNotification(config.userNotification); - } - - this.logger.info('Dual notification scheduled successfully'); - } - - /** - * Register callback - */ - public async registerCallback(name: string, _callback: (...args: unknown[]) => void): Promise { - this.logger.info(`Registering callback: ${name}`); - // In a real implementation, this would register the callback - this.logger.info(`Callback ${name} registered successfully`); - } - - /** - * Get dual schedule status - */ - public async getDualScheduleStatus(): Promise> { - return { - contentFetch: { - enabled: true, - lastFetch: new Date().toISOString(), - nextFetch: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString() - }, - userNotification: { - enabled: true, - lastNotification: new Date().toISOString(), - nextNotification: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString() - } - }; - } - - /** - * Cancel all notifications - */ - public async cancelAllNotifications(): Promise { - this.logger.info('Cancelling all notifications'); - this.logger.info('All notifications cancelled successfully'); - } - - /** - * Simulate content fetch using Endorser.ch API patterns - */ - private async simulateContentFetch(config: Record): Promise { - this.logger.info('Simulating content fetch from Endorser.ch API'); - - try { - // Simulate parallel API requests - const testData = this.config.testData; - - // Mock offers to person - const offersToPerson = { - data: testData.mockOffers, - hitLimit: false - }; - - // Mock offers to projects - const offersToProjects = { - data: [], - hitLimit: false - }; - - // Mock starred project changes - const starredChanges = { - data: testData.mockProjects, - hitLimit: false - }; - - this.logger.info('Content fetch simulation completed', { - offersToPerson: offersToPerson.data.length, - offersToProjects: offersToProjects.data.length, - starredChanges: starredChanges.data.length - }); - - // Call success callback if provided - if (config.callbacks?.onSuccess) { - await config.callbacks.onSuccess({ - offersToPerson, - offersToProjects, - starredChanges - }); - } - } catch (error) { - this.logger.error('Content fetch simulation failed', error); - if (config.callbacks?.onError) { - await config.callbacks.onError(error); - } - } - } - - /** - * Simulate user notification - */ - private async simulateUserNotification(config: Record): Promise { - this.logger.info('Simulating user notification', { - title: config.title, - body: config.body, - time: config.schedule - }); - this.logger.info('User notification simulation completed'); - } -} diff --git a/test-apps/shared/typescript/EndorserAPIClient.ts b/test-apps/shared/typescript/EndorserAPIClient.ts deleted file mode 100644 index 29d8a29..0000000 --- a/test-apps/shared/typescript/EndorserAPIClient.ts +++ /dev/null @@ -1,659 +0,0 @@ -/** - * EndorserAPIClient.ts - * - * Complete implementation of Endorser.ch API client for TimeSafari notifications - * Supports offers, projects, people, and items notification types with pagination - * - * @author Matthew Raymer - * @version 4.0.0 - */ - -import { - OffersResponse, - OffersToPlansResponse, - PlansLastUpdatedResponse, - TimeSafariNotificationBundle, - TimeSafariUserConfig, - TimeSafariNotificationType -} from '../definitions'; - -export interface EndorserAPIConfig { - baseUrl: string; - timeoutMs: number; - maxRetries: number; - enableParallel: boolean; - maxConcurrent: number; - jwtSecret?: string; -} - -export interface EndorserAPIRequest { - endpoint: string; - params?: Record; - body?: Record; - method: 'GET' | 'POST'; - timeoutMs?: number; - authRequired: boolean; -} - -export interface EndorserAPIError { - statusCode: number; - message: string; - endpoint: string; - timestamp: number; - retryable: boolean; -} - -/** - * Default EndorserAPI configuration for TimeSafari - */ -export const TIMESAFARI_ENDSORER_CONFIG: EndorserAPIConfig = { - baseUrl: 'https://api.endorser.ch', - timeoutMs: 15000, - maxRetries: 3, - enableParallel: true, - maxConcurrent: 3, - jwtSecret: process.env.ENDORSER_JWT_SECRET -}; - -/** - * Endorser.ch API Client for TimeSafari integrations - */ -export class EndorserAPIClient { - private config: EndorserAPIConfig; - private authToken?: string; - private rateLimiter: Map = new Map(); - private requestCache: Map = new Map(); - - constructor(config: Partial = {}) { - this.config = { ...TIMESAFARI_ENDSORER_CONFIG, ...config }; - } - - /** - * Set authentication token for API requests - */ - setAuthToken(token: string): void { - this.authToken = token; - } - - /** - * Generate JWT token for DID-based authentication - */ - async generateJWTForDID(activeDid: string, _jwtSecret?: string): Promise { - try { - // In a real implementation, this would use a JWT library like di-djwt - // For Phase 4, we'll generate a mock JWT structure - const issuedAt = Math.floor(Date.now() / 1000); - const expiresAt = issuedAt + 3600; // 1 hour expiration - - const payload = { - iss: activeDid, - sub: activeDid, - aud: 'endorser-api', - exp: expiresAt, - iat: issuedAt, - jti: `notification-${Date.now()}-${Math.random().toString(36).substr(2, 9)}` - }; - - // Mock JWT generation - in production, would use proper signing - const header = btoa(JSON.stringify({ alg: 'ES256K', typ: 'JWT' })); - const payload_b64 = btoa(JSON.stringify(payload)); - const signature = btoa(`${activeDid}-${Date.now()}-mock-signature`); - - return `${header}.${payload_b64}.${signature}`; - - } catch (error) { - console.error('Error generating JWT for DID:', error); - throw new Error(`JWT generation failed: ${error instanceof Error ? error.message : 'Unknown error'}`); - } - } - - /** - * Fetch offers directed to a specific person - * Endpoint: GET /api/v2/report/offers?recipientId={did} - */ - async fetchOffersToPerson( - recipientDid: string, - afterId?: string, - beforeId?: string, - options?: { validThrough?: string; offeredByDid?: string } - ): Promise { - try { - const params = new URLSearchParams(); - params.set('recipientId', recipientDid); - if (afterId) params.set('afterId', afterId); - if (beforeId) params.set('beforeId', beforeId); - if (options?.validThrough) params.set('validThrough', options.validThrough); - if (options?.offeredByDid) params.set('offeredByDid', options.offeredByDid); - - const response = await this.request({ - endpoint: `/api/v2/report/offers`, - method: 'GET', - params: Object.fromEntries(params), - authRequired: true - }); - - return response as OffersResponse; - - } catch (error) { - console.error('Error fetching offers to person:', error instanceof Error ? error.message : 'Unknown error'); - return { data: [], hitLimit: false }; - } - } - - /** - * Fetch offers directed to projects owned by authenticated user - * Endpoint: GET /api/v2/report/offersToPlansOwnedByMe - */ - async fetchOffersToProjectsOwnedByMe( - afterId?: string, - beforeId?: string - ): Promise { - try { - const params: Record = {}; - if (afterId) params.afterId = afterId; - if (beforeId) params.beforeId = beforeId; - - const response = await this.request({ - endpoint: `/api/v2/report/offersToPlansOwnedByMe`, - method: 'GET', - params, - authRequired: true - }); - - return response as OffersToPlansResponse; - - } catch (error) { - console.error('Error fetching offers to projects:', error instanceof Error ? error.message : 'Unknown error'); - return { data: [], hitLimit: false }; - } - } - - /** - * Fetch changes to specific projects since a given point - * Endpoint: POST /api/v2/report/plansLastUpdatedBetween - */ - async fetchProjectsLastUpdated( - planIds: string[], - afterId?: string, - beforeId?: string - ): Promise { - try { - const body: Record = { - planIds - }; - if (afterId) body.afterId = afterId; - if (beforeId) body.beforeId = beforeId; - - const response = await this.request({ - endpoint: `/api/v2/report/plansLastUpdatedBetween`, - method: 'POST', - body, - authRequired: true - }); - - return response as PlansLastUpdatedResponse; - - } catch (error) { - console.error('Error fetching project updates:', error instanceof Error ? error.message : 'Unknown error'); - return { data: [], hitLimit: false }; - } - } - - /** - * Fetch all TimeSafari notification data in parallel - * This is the main method for TimeSafari integration - */ - async fetchAllTimeSafariNotifications( - userConfig: TimeSafariUserConfig - ): Promise { - const startTime = Date.now(); - const bundle: TimeSafariNotificationBundle = { - offersToPerson: undefined, - offersToProjects: undefined, - projectUpdates: undefined, - fetchTimestamp: startTime, - success: false, - metadata: { - activeDid: userConfig.activeDid, - fetchDurationMs: 0, - cachedResponses: 0, - networkResponses: 0 - } - }; - - try { - // Fetching all TimeSafari notifications for user - - // Ensure authentication - const token = await this.generateJWTForDID(userConfig.activeDid); - this.setAuthToken(token); - - const requests: Promise[] = []; - - // 1. Offers to Person - if (userConfig.fetchOffersToPerson !== false) { - requests.push( - this.fetchOffersToPerson( - userConfig.activeDid, - userConfig.lastKnownOfferId, - undefined - ).then(response => { - bundle.offersToPerson = response; - if (bundle.metadata) { - bundle.metadata.networkResponses++; - } - }) - ); - } - - // 2. Offers it Plans Owned by Current User - if (userConfig.fetchOffersToProjects !== false) { - requests.push( - this.fetchOffersToProjectsOwnedByMe(userConfig.lastKnownOfferId) - .then(response => { - bundle.offersToProjects = response; - if (bundle.metadata) { - bundle.metadata.networkResponses++; - } - }) - ); - } - - // 3. Starred Project Changes - if (userConfig.fetchProjectUpdates && userConfig.starredPlanIds && userConfig.starredPlanIds.length > 0) { - requests.push( - this.fetchProjectsLastUpdated( - userConfig.starredPlanIds, - userConfig.lastKnownPlanId, - undefined - ).then(response => { - bundle.projectUpdates = response; - if (bundle.metadata) { - bundle.metadata.networkResponses++; - } - }) - ); - } - - // Execute all requests in parallel - if (requests.length > 0) { - await Promise.allSettled(requests); - } - - bundle.success = true; - - } catch (error) { - console.error('Error fetching TimeSafari notifications:', error instanceof Error ? error.message : 'Unknown error'); - bundle.success = false; - bundle.error = error instanceof Error ? error.message : 'Unknown error'; - - // Ensure we have partial data even on error - if (bundle.metadata) { - bundle.metadata.networkResponses = bundle.metadata.networkResponses || 0; - } - - } finally { - if (bundle.metadata) { - bundle.metadata.fetchDurationMs = Date.now() - startTime; - } - if (bundle.metadata) { - // TimeSafari notification fetch completed - } - } - - return bundle; - } - - /** - * Generate TimeSafari-specific notification content from API responses - */ - generateTimeSafariNotifications(bundle: TimeSafariNotificationBundle): TimeSafariNotificationType[] { - const notifications: TimeSafariNotificationType[] = []; - - try { - // Generate offer notifications - this.generateOfferNotifications(bundle, notifications); - - // Generate project notification notifications - this.generateProjectNotifications(bundle, notifications); - - // Generate people notifications (derived from offers and projects) - this.generatePeopleNotifications(bundle, notifications); - - // Generate items notifications (derived from projects) - this.generateItemNotifications(bundle, notifications); - - // Generated TimeSafari notifications - return notifications; - - } catch (error) { - console.error('Error generating TimeSafari notifications:', error); - return []; - } - } - - /** - * Generate notification-specific notification content - */ - private generateOfferNotifications( - bundle: TimeSafariNotificationBundle, - notifications: TimeSafariNotificationType[] - ): void { - try { - // New offers to person - if (bundle.offersToPerson?.data && bundle.offersToPerson.data.length > 0) { - bundle.offersToPerson.data.forEach(offer => { - notifications.push({ - type: 'offer', - subtype: 'new_to_me', - offer, - notificationPriority: 'high', - timestamp: Date.now() - }); - }); - } - - // New offers to projects owned by user - if (bundle.offersToProjects?.data && bundle.offersToProjects.data.length > 0) { - bundle.offersToProjects.data.forEach(offerToPlan => { - notifications.push({ - type: 'offer', - subtype: 'new_to_projects', - offer: { - jwtId: offerToPlan.jwtId, - handleId: offerToPlan.handleId, - issuedAt: offerToPlan.issuedAt, - offeredByDid: offerToPlan.offeredByDid, - recipientDid: '', // Placeholder - would be derived from context - unit: offerToPlan.unit, - amount: offerToPlan.amount, - amountGiven: offerToPlan.amountGiven, - amountGivenConfirmed: 0, // Placeholder - objectDescription: offerToPlan.objectDescription, - validThrough: offerToPlan.validThrough, - fullClaim: {} // Placeholder - }, - relevantProjects: [], // Would be populated from plan lookup - notificationPriority: 'medium', - timestamp: Date.now() - }); - }); - } - - } catch (error) { - console.error('Error generating offer notifications:', error); - } - } - - /** - * Generate project-specific notification content - */ - private generateProjectNotifications( - bundle: TimeSafariNotificationBundle, - notifications: TimeSafariNotificationType[] - ): void { - try { - if (bundle.projectUpdates?.data && bundle.projectUpdates.data.length > 0) { - bundle.projectUpdates.data.forEach(update => { - notifications.push({ - type: 'project', - subtype: 'favorite_and_changed', - project: update.plan, - previousClaim: update.wrappedClaimBefore, - notificationPriority: 'medium', - timestamp: Date.now() - }); - }); - } - - } catch (error) { - console.error('Error generating project notifications:', error); - } - } - - /** - * Generate people-specific notification content - */ - private generatePeopleNotifications( - bundle: TimeSafariNotificationBundle, - notifications: TimeSafariNotificationType[] - ): void { - try { - // Extract unique people from offers - const people = new Set(); - - if (bundle.offersToPerson?.data) { - bundle.offersToPerson.data.forEach(offer => { - if (offer.offeredByDid) people.add(offer.offeredByDid); - }); - } - - // Generate people notifications - people.forEach(did => { - notifications.push({ - type: 'person', - subtype: 'with_content_and_new', - personDid: did, - person: { did, name: `User-${did.slice(-6)}` }, // Placeholder name - notificationPriority: 'low', - timestamp: Date.now() - }); - }); - - } catch (error) { - console.error('Error generating people notifications:', error); - } - } - - /** - * Generate items-specific notification content - */ - private generateItemNotifications( - bundle: TimeSafariNotificationBundle, - notifications: TimeSafariNotificationType[] - ): void { - try { - if (bundle.projectUpdates?.data) { - bundle.projectUpdates.data.forEach(update => { - notifications.push({ - type: 'item', - subtype: 'favorite_and_changed', - itemId: update.plan.jwtId, - item: { - id: update.plan.jwtId, - name: update.plan.name, - type: 'project' - }, - notificationPriority: 'low', - timestamp: Date.now() - }); - }); - } - - } catch (error) { - console.error('Error generating item notifications:', error); - } - } - - /** - * Execute authenticated request with retry logic - */ - private async request(requestConfig: EndorserAPIRequest): Promise { - const url = `${this.config.baseUrl}${requestConfig.endpoint}`; - - try { - // Check rate limiting - this.checkRateLimit(requestConfig.endpoint); - - // Check cache - const cached = this.getCachedResponse(url); - if (cached) { - // Returning cached response - return cached; - } - - // Prepare headers - const headers: Record = { - 'Content-Type': 'application/json', - 'User-Agent': 'TimeSafari-DailyNotificationPlugin/1.0.0' - }; - - // Add authentication if required - if (requestConfig.authRequired && this.authToken) { - headers['Authorization'] = `Bearer ${this.authToken}`; - } - - // Prepare request options - const options: RequestInit = { - method: requestConfig.method, - headers, - signal: AbortSignal.timeout(requestConfig.timeoutMs || this.config.timeoutMs) - }; - - // Add body for POST requests - if (requestConfig.method === 'POST' && requestConfig.body) { - options.body = JSON.stringify(requestConfig.body); - } else if (requestConfig.method === 'GET' && requestConfig.params) { - // Add query parameters for GET requests - const params = new URLSearchParams(requestConfig.params); - const fullUrl = `${url}?${params}`; - return this.executeRequest(fullUrl, options, requestConfig.endpoint); - } - - return await this.executeRequest(url, options, requestConfig.endpoint); - - } catch (error) { - console.error(`Error executing request to ${requestConfig.endpoint}:`, error); - throw error; - } - } - - /** - * Execute HTTP request with retry logic - */ - private async executeRequest(url: string, options: RequestInit, endpoint: string): Promise { - let lastError: Error | undefined; - - for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) { - try { - // Executing request attempt - - const response = await fetch(url, options); - - if (response.ok) { - const data = await response.json(); - - // Cache successful response - this.cacheResponse(url, data); - - // Update rate limiter - this.rateLimiter.set(endpoint, Date.now()); - - return data; - - } else if (response.status === 401 || response.status === 403) { - throw new EndorserAPIError( - response.status, - 'Authentication failed', - endpoint, - Date.now(), - false - ); - - } else if (response.status >= 500) { - lastError = new EndorserAPIError( - response.status, - 'Server error - retryable', - endpoint, - Date.now(), - true - ); - - // Continue to retry for server errors - - } else { - throw new EndorserAPIError( - response.status, - 'Client error', - endpoint, - Date.now(), - false - ); - } - - } catch (error) { - lastError = error instanceof EndorserAPIError ? error : new Error(error instanceof Error ? error.message : 'Unknown error'); - - if (!(lastError instanceof EndorserAPIError && lastError.retryable) || attempt >= this.config.maxRetries) { - throw lastError; - } - - // Wait before retry with exponential backoff - const waitTime = Math.min(1000 * Math.pow(2, attempt), 5000); - // Request failed, retrying - await new Promise(resolve => setTimeout(resolve, waitTime)); - } - } - - throw lastError; - } - - /** - * Check and enforce rate limiting - */ - private checkRateLimit(endpoint: string): void { - const lastRequest = this.rateLimiter.get(endpoint); - if (lastRequest) { - const timeSinceLastRequest = Date.now() - lastRequest; - if (timeSinceLastRequest < 1000) { // 1 second between requests - // Rate limiting detected, waiting - throw new Error('Rate limited'); - } - } - } - - /** - * Cache response for future use - */ - private cacheResponse(url: string, data: unknown): void { - this.requestCache.set(url, { - data, - timestamp: Date.now() - }); - } - - /** - * Get cached response if fresh enough - */ - private getCachedResponse(url: string): unknown { - const cached = this.requestCache.get(url); - if (cached && (Date.now() - cached.timestamp) < 30000) { // 30 seconds cache - return cached.data; - } - return null; - } - - /** - * Clear cache (useful after activeDid changes) - */ - clearCache(): void { - this.requestCache.clear(); - // EndorserAPI cache cleared - } -} - -/** - * Error class for EndorserAPI errors - */ -export class EndorserAPIError extends Error { - constructor( - public statusCode: number, - public message: string, - public endpoint: string, - public timestamp: number, - public retryable: boolean - ) { - super(message); - this.name = 'EndorserAPIError'; - } -} diff --git a/test-apps/shared/typescript/SecurityManager.ts b/test-apps/shared/typescript/SecurityManager.ts deleted file mode 100644 index ea4a40e..0000000 --- a/test-apps/shared/typescript/SecurityManager.ts +++ /dev/null @@ -1,554 +0,0 @@ -/** - * SecurityManager.ts - * - * Enhanced security manager for DID-based authentication and cryptographic verification - * Supports JWT generation, signature verification, and secure credential management - * - * @author Matthew Raymer - * @version 4.0.0 - */ - -// PlatformService import removed - not used in Phase 4 implementation - -export interface DIDCredentials { - did: string; - privateKey?: string; // Encrypted private key - publicKey?: string; // Public key in JWK format - keyType: 'secp256k1' | 'Ed25519' | 'RSA'; - keyManagement: 'local' | 'platform_service' | 'secure_element'; -} - -export interface JWTClaims { - iss: string; // Issuer DID - sub: string; // Subject DID - aud: string; // Audience - exp: number; // Expiration time - iat: number; // Issued at - jti: string; // JWT ID - nonce?: string; // Nonce for replay protection - scope?: string; // Permission scope -} - -export interface SecurityConfig { - enableCryptoSigning: boolean; - enableJWTGeneration: boolean; - enableCredentialStorage: boolean; - jwtExpirationMinutes: number; - signatureAlgorithm: 'ES256K' | 'EdDSA' | 'RS256'; - keyDerivation: boolean; - credentialStorage: 'secure_element' | 'keychain' | 'encrypted_storage'; -} - -export interface CryptoOperation { - success: boolean; - data?: Record; - error?: string; - timestamp: number; - operation: string; -} - -/** - * Default security configuration for TimeSafari - */ -export const TIMESAFARI_SECURITY_CONFIG: SecurityConfig = { - enableCryptoSigning: true, - enableJWTGeneration: true, - enableCredentialStorage: true, - jwtExpirationMinutes: 60, - signatureAlgorithm: 'ES256K', - keyDerivation: true, - credentialStorage: 'secure_element' -}; - -/** - * Secure credential storage interface - */ -interface CredentialStorage { - storeCredentials(did: string, credentials: DIDCredentials): Promise; - retrieveCredentials(did: string): Promise; - deleteCredentials(did: string): Promise; - listCredentials(): Promise; -} - -/** - * Secure element credential storage implementation - */ -class SecureElementStorage implements CredentialStorage { - async storeCredentials(did: string, credentials: DIDCredentials): Promise { - try { - // In a real implementation, this would use platform-specific secure storage - // For Phase 4, we'll use a mock secure storage - const secureData = { - did: credentials.did, - keyType: credentials.keyType, - timestamp: Date.now(), - encrypted: true - }; - - await this.writeToSecureElement(`cred_${did}`, JSON.stringify(secureData)); - return true; - - } catch (error) { - console.error('Error storing credentials:', error instanceof Error ? error.message : 'Unknown error'); - return false; - } - } - - async retrieveCredentials(did: string): Promise { - try { - const data = await this.readFromSecureElement(`cred_${did}`); - if (data) { - const parsed = JSON.parse(data); - return { - did: parsed.did, - keyType: parsed.keyType, - keyManagement: 'secure_element' - }; - } - return undefined; - - } catch (error) { - console.error('Error retrieving credentials:', error instanceof Error ? error.message : 'Unknown error'); - return undefined; - } - } - - async deleteCredentials(did: string): Promise { - try { - await this.deleteFromSecureElement(`cred_${did}`); - return true; - - } catch (error) { - console.error('Error deleting credentials:', error instanceof Error ? error.message : 'Unknown error'); - return false; - } - } - - async listCredentials(): Promise { - try { - // Mock implementation - would list actual secure element entries - return ['did:example:alice', 'did:example:bob']; - - } catch (error) { - console.error('Error listing credentials:', error); - return []; - } - } - - private async writeToSecureElement(_key: string, _data: string): Promise { - // Mock secure element write - in production would use platform APIs - // Mock secure element write operation - } - - private async readFromSecureElement(_key: string): Promise { - // Mock secure element read - in production would use platform APIs - // Mock secure element read operation - return `{"did":"${_key}", "keyType":"secp256k1", "timestamp":${Date.now()}, "encrypted":true}`; - } - - private async deleteFromSecureElement(_key: string): Promise { - // Mock secure element delete - in production would use platform APIs - // Mock secure element delete operation - } -} - -/** - * Enhanced Security Manager for TimeSafari DID operations - */ -export class SecurityManager { - private config: SecurityConfig; - private credentialStorage: CredentialStorage; - private activeDid?: string; - private activeCredentials?: DIDCredentials; - private operationHistory: CryptoOperation[] = []; - - constructor(config: Partial = {}) { - this.config = { ...TIMESAFARI_SECURITY_CONFIG, ...config }; - this.credentialStorage = new SecureElementStorage(); - } - - /** - * Initialize security manager with active DID - */ - async initialize(activeDid: string): Promise { - try { - // Initializing SecurityManager for DID - - this.activeDid = activeDid; - - // Retrieve stored credentials - this.activeCredentials = await this.credentialStorage.retrieveCredentials(activeDid); - - if (!this.activeCredentials) { - // No stored credentials found, initializing new ones - const newCredentials = await this.generateNewCredentials(activeDid); - - if (newCredentials) { - await this.credentialStorage.storeCredentials(activeDid, newCredentials); - this.activeCredentials = newCredentials; - } - } - - // SecurityManager initialized successfully - return true; - - } catch (error) { - console.error('Error initializing SecurityManager:', error); - return false; - } - } - - /** - * Generate new DID credentials - */ - async generateNewCredentials(did: string): Promise { - try { - // Generating new credentials for DID - - const credentials: DIDCredentials = { - did, - keyType: this.config.signatureAlgorithm === 'ES256K' ? 'secp256k1' - : this.config.signatureAlgorithm === 'EdDSA' ? 'Ed25519' - : 'RSA', - keyManagement: 'secure_element' - }; - - // Generate cryptographic keys based on platform capabilities - if (this.config.enableCryptoSigning) { - const keys = await this.generateKeys(credentials.keyType); - credentials.privateKey = keys.privateKey; - credentials.publicKey = keys.publicKey; - } - - this.logOperation({ - success: true, - timestamp: Date.now(), - operation: 'generate_credentials' - }); - - return credentials; - - } catch (error) { - console.error('Error generating credentials:', error); - this.logOperation({ - success: false, - error: error instanceof Error ? error.message : 'Unknown error', - timestamp: Date.now(), - operation: 'generate_credentials' - }); - return null; - } - } - - /** - * Generate cryptographic keys - */ - private async generateKeys(keyType: 'secp256k1' | 'Ed25519' | 'RSA'): Promise<{ privateKey: string; publicKey: string }> { - try { - // In a real implementation, this would use platform cryptographic APIs - // For Phase 4, we'll generate mock keys - - const timestamp = Date.now(); - const mockKeys = { - privateKey: `mock_private_key_${keyType}_${timestamp}`, - publicKey: `mock_public_key_${keyType}_${timestamp}` - }; - - // Generated keys for secure operations - return mockKeys; - - } catch (error) { - console.error('Error generating keys:', error); - throw error instanceof Error ? error : new Error('Unknown error'); - } - } - - /** - * Generate JWT token for authentication - */ - async generateJWT(claims: Partial, audience = 'endorser-api'): Promise { - try { - if (!this.activeDid || !this.activeCredentials) { - throw new Error('No active DID or credentials available'); - } - - // Generating JWT for DID - - const now = Math.floor(Date.now() / 1000); - const fullClaims: JWTClaims = { - iss: this.activeDid, - sub: this.activeDid, - aud: audience, - exp: now + (this.config.jwtExpirationMinutes * 60), - iat: now, - jti: `jwt_${now}_${Math.random().toString(36).substr(2, 9)}`, - nonce: this.generateNonce(), - scope: 'notifications', - ...claims - }; - - let jwt: string; - - if (this.config.enableCryptoSigning && this.activeCredentials.privateKey) { - // Generate signed JWT - jwt = await this.generateSignedJWT(fullClaims); - } else { - // Generate unsigned JWT (for development/testing) - jwt = await this.generateUnsignedJWT(fullClaims); - } - - this.logOperation({ - success: true, - data: { iss: fullClaims.iss, exp: fullClaims.exp }, - timestamp: Date.now(), - operation: 'generate_jwt' - }); - - // JWT generated successfully - return jwt; - - } catch (error) { - console.error('Error generating JWT:', error instanceof Error ? error.message : 'Unknown error'); - this.logOperation({ - success: false, - error: error instanceof Error ? error.message : 'Unknown error', - timestamp: Date.now(), - operation: 'generate_jwt' - }); - return null; - } - } - - /** - * Generate signed JWT with cryptographic signature - */ - private async generateSignedJWT(claims: JWTClaims): Promise { - try { - // In a real implementation, this would use proper JWT signing libraries - // For Phase 4, we'll create a mock signed JWT structure - - const header = { - alg: this.config.signatureAlgorithm, - typ: 'JWT' - }; - - const encodedHeader = btoa(JSON.stringify(header)); - const encodedPayload = btoa(JSON.stringify(claims)); - - // Mock signature generation - const signature = btoa(`signature_${claims.jti}_${Date.now()}`); - - const jwt = `${encodedHeader}.${encodedPayload}.${signature}`; - - // Generated signed JWT - return jwt; - - } catch (error) { - console.error('Error generating signed JWT:', error); - throw error; - } - } - - /** - * Generate unsigned JWT (for development/testing) - */ - private async generateUnsignedJWT(claims: JWTClaims): Promise { - try { - const header = { - alg: 'none', - typ: 'JWT' - }; - - const encodedHeader = btoa(JSON.stringify(header)); - const encodedPayload = btoa(JSON.stringify(claims)); - - const jwt = `${encodedHeader}.${encodedPayload}.`; - - // Generated unsigned JWT (development mode) - return jwt; - - } catch (error) { - console.error('Error generating unsigned JWT:', error); - throw error; - } - } - - /** - * Verify JWT signature and claims - */ - async verifyJWT(token: string): Promise { - try { - // Verifying JWT token - - const parts = token.split('.'); - if (parts.length !== 3) { - throw new Error('Invalid JWT format'); - } - - const [headerEncoded, payloadEncoded, signature] = parts; - - // Decode header and payload - const header = JSON.parse(atob(headerEncoded)); - const claims = JSON.parse(atob(payloadEncoded)); - - // Verify expiration - const now = Math.floor(Date.now() / 1000); - if (claims.exp && claims.exp < now) { - throw new Error('JWT expired'); - } - - // Verify signature (in production, would use proper verification) - if (header.alg !== 'none' && !this.verifySignature(header, payloadEncoded, signature)) { - throw new Error('Invalid JWT signature'); - } - - this.logOperation({ - success: true, - data: 'verified claims', - timestamp: Date.now(), - operation: 'verify_jwt' - }); - - // JWT verified successfully - return claims; - - } catch (error) { - console.error('Error verifying JWT:', error instanceof Error ? error.message : 'Unknown error'); - this.logOperation({ - success: false, - error: error instanceof Error ? error.message : 'Unknown error', - timestamp: Date.now(), - operation: 'verify_jwt' - }); - return null; - } - } - - /** - * Verify cryptographic signature - */ - private verifySignature(_header: Record, _payload: string, signature: string): boolean { - try { - // In a real implementation, this would verify the signature using the public key - // For Phase 4, we'll perform basic signature format validation - - return signature.length > 0 && !signature.endsWith('.'); - - } catch (error) { - console.error('Error verifying signature:', error); - return false; - } - } - - /** - * Generate cryptographically secure nonce - */ - private generateNonce(): string { - // Generate a secure nonce for replay protection - const bytes = new Uint8Array(16); - if (typeof crypto !== 'undefined' && crypto.getRandomValues) { - crypto.getRandomValues(bytes); - } else { - // Fallback for environments without crypto.getRandomValues - for (let i = 0; i < bytes.length; i++) { - bytes[i] = Math.floor(Math.random() * 256); - } - } - - return Array.from(bytes, byte => byte.toString(16).padStart(2, '0')).join(''); - } - - /** - * Log cryptographic operations for audit and debugging - */ - private logOperation(operation: CryptoOperation): void { - this.operationHistory.push(operation); - - // Keep only last 100 operations - if (this.operationHistory.length > 100) { - this.operationHistory = this.operationHistory.slice(-100); - } - } - - /** - * Get operation history for audit purposes - */ - getOperationHistory(): CryptoOperation[] { - return [...this.operationHistory]; - } - - /** - * Clear credentials and reset security manager - */ - async reset(): Promise { - try { - // Clear active credentials - this.activeDid = undefined; - this.activeCredentials = undefined; - - // Clear operation history - this.operationHistory = []; - - // SecurityManager reset completed - - } catch (error) { - console.error('Error resetting SecurityManager:', error); - } - } - - /** - * Update active DID (for identity changes) - */ - async updateActiveDid(newActiveDid: string): Promise { - try { - // Updating active DID - - // Retrieve credentials for new DID - const credentials = await this.credentialStorage.retrieveCredentials(newActiveDid); - - if (!credentials) { - // No credentials found for new DID, generating new ones - const newCredentials = await this.generateNewCredentials(newActiveDid); - - if (newCredentials) { - await this.credentialStorage.storeCredentials(newActiveDid, newCredentials); - this.activeCredentials = newCredentials; - } else { - return false; - } - } else { - this.activeCredentials = credentials; - } - - this.activeDid = newActiveDid; - - // Active DID updated successfully - return true; - - } catch (error) { - console.error('Error updating active DID:', error); - return false; - } - } - - /** - * Get current active DID - */ - getActiveDid(): string | undefined { - return this.activeDid; - } - - /** - * Get security configuration - */ - getSecurityConfig(): SecurityConfig { - return { ...this.config }; - } - - /** - * Check if security manager is properly initialized - */ - isInitialized(): boolean { - return !!this.activeDid && !!this.activeCredentials; - } -} diff --git a/test-apps/shared/typescript/TimeSafariNotificationManager.ts b/test-apps/shared/typescript/TimeSafariNotificationManager.ts deleted file mode 100644 index ffe1c95..0000000 --- a/test-apps/shared/typescript/TimeSafariNotificationManager.ts +++ /dev/null @@ -1,640 +0,0 @@ -/** - * TimeSafariNotificationManager.ts - * - * High-level TimeSafari notification manager integrating EndorserAPI and security - * Manages notification generation, user preferences, and TimeSafari-specific features - * - * @author Matthew Raymer - * @version 4.0.0 - */ - -import { - EndorserAPIClient, - TIMESAFARI_ENDSORER_CONFIG -} from './EndorserAPIClient'; -import { - SecurityManager, - TIMESAFARI_SECURITY_CONFIG -} from './SecurityManager'; -import { - TimeSafariUserConfig, - EnhancedTimeSafariNotification as TimeSafariNotification, - TimeSafariNotificationType, - CoordinationStatus -} from '../definitions'; - -export interface TimeSafariPreferences { - notificationTypes: { - offers: boolean; - projects: boolean; - people: boolean; - items: boolean; - }; - offerSubtypes: { - new_to_me: boolean; - changed_to_me: boolean; - new_to_projects: boolean; - changed_to_projects: boolean; - new_to_favorites: boolean; - changed_to_favorites: boolean; - }; - projectSubtypes: { - local_and_new: boolean; - local_and_changed: boolean; - with_content_and_new: boolean; - favorite_and_changed: boolean; - }; - peopleSubtypes: { - local_and_new: boolean; - local_and_changed: boolean; - with_content_and_new: boolean; - favorite_and_changed: boolean; - }; - itemsSubtypes: { - local_and_new: boolean; - local_and_changed: boolean; - favorite_and_changed: boolean; - }; - frequency: { - immediate: boolean; - daily: boolean; - weekly: boolean; - custom?: string; // Cron expression - }; - priority: 'low' | 'medium' | 'high'; - sound: boolean; - vibration: boolean; - badge: boolean; -} - -export interface TimeSafariUser { - activeDid: string; - preferences: TimeSafariPreferences; - starredPlanIds: string[]; - favoritePersonIds: string[]; - favoriteItemIds: string[]; - lastKnownOfferId?: string; - lastKnownPlanId?: string; - coordinationStatus?: CoordinationStatus; -} - -export interface NotificationGenerationOptions { - forceFetch: boolean; - includeMetadata: boolean; - filterByPriority: boolean; - maxNotifications: number; - cacheTtl: number; // TTL in milliseconds -} - -/** - * Default TimeSafari preferences - */ -export const DEFAULT_TIMESAFARI_PREFERENCES: TimeSafariPreferences = { - notificationTypes: { - offers: true, - projects: true, - people: false, - items: true - }, - offerSubtypes: { - new_to_me: true, - changed_to_me: false, - new_to_projects: true, - changed_to_projects: false, - new_to_favorites: true, - changed_to_favorites: false - }, - projectSubtypes: { - local_and_new: false, - local_and_changed: false, - with_content_and_new: true, - favorite_and_changed: true - }, - peopleSubtypes: { - local_and_new: false, - local_and_changed: false, - with_content_and_new: false, - favorite_and_changed: false - }, - itemsSubtypes: { - local_and_new: false, - local_and_changed: false, - favorite_and_changed: true - }, - frequency: { - immediate: true, - daily: true, - weekly: false - }, - priority: 'medium', - sound: true, - vibration: true, - badge: true -}; - -/** - * TimeSafari-specific notification manager - */ -export class TimeSafariNotificationManager { - private apiClient: EndorserAPIClient; - private securityManager: SecurityManager; - private user?: TimeSafariUser; - private cache: Map = new Map(); - private activeGeneration = new Set(); - - constructor() { - this.apiClient = new EndorserAPIClient(TIMESAFARI_ENDSORER_CONFIG); - this.securityManager = new SecurityManager(TIMESAFARI_SECURITY_CONFIG); - } - - /** - * Initialize manager for specific TimeSafari user - */ - async initialize(user: TimeSafariUser): Promise { - try { - // Initializing TimeSafariNotificationManager for user - - // Initialize security manager with active DID - const securityInitialized = await this.securityManager.initialize(user.activeDid); - if (!securityInitialized) { - console.error('Failed to initialize security manager'); - return false; - } - - // Generate JWT token for API authentication - const token = await this.securityManager.generateJWT({ - scope: 'notifications' - }); - - if (token) { - this.apiClient.setAuthToken(token); - } - - // Set user configuration - this.user = user; - - // TimeSafariNotificationManager initialized successfully - return true; - - } catch (error) { - console.error('Error initializing TimeSafariNotificationManager:', error); - return false; - } - } - - /** - * Generate TimeSafari-specific notifications based on user preferences - */ - async generateNotifications( - options: Partial = {} - ): Promise { - if (!this.user) { - throw new Error('TimeSafariNotificationManager not initialized'); - } - - // const generationId = `generation_${Date.now()}_${Math.random().toString(36).substr(2, 6)}`; - const generationOptions: NotificationGenerationOptions = { - forceFetch: false, - includeMetadata: true, - filterByPriority: true, - maxNotifications: 50, - cacheTtl: 300000, // 5 minutes - ...options - }; - - try { - // Starting notification generation - - // Prevent concurrent generations for same user - if (this.activeGeneration.has(this.user.activeDid)) { - // Generation already in progress, skipping - return []; - } - - this.activeGeneration.add(this.user.activeDid); - - // Check cache first - const cached = options.forceFetch ? null : this.getCachedNotifications(); - if (cached) { - // Returning cached notifications - return this.filterNotificationsByPreferences(cached, generationOptions); - } - - // Fetch fresh data from EndorserAPI - const userConfig = this.buildUserConfig(); - const bundle = await this.apiClient.fetchAllTimeSafariNotifications(userConfig); - - if (!bundle.success) { - console.error('Failed to fetch TimeSafari data:', bundle.error); - return this.generateFallbackNotifications(); - } - - // Generate TimeSafari notifications - const allNotifications = this.apiClient.generateTimeSafariNotifications(bundle); - - // Cache the results - this.cacheNotifications(allNotifications, bundle.fetchTimestamp); - - // Filter by user preferences - const filteredNotifications = this.filterNotificationsByPreferences( - allNotifications, - generationOptions - ); - - // Generated notifications successfully - - return filteredNotifications; - - } catch (error) { - console.error('Error generating notifications:', error); - return this.generateFallbackNotifications(); - - } finally { - this.activeGeneration.delete(this.user.activeDid); - } - } - - /** - * Build user configuration from user preferences and state - */ - private buildUserConfig(): TimeSafariUserConfig { - if (!this.user) { - throw new Error('User not initialized'); - } - - return { - activeDid: this.user.activeDid, - starredPlanIds: this.user.starredPlanIds || [], - lastKnownOfferId: this.user.lastKnownOfferId, - lastKnownPlanId: this.user.lastKnownPlanId, - fetchOffersToPerson: this.user.preferences.notificationTypes.offers, - fetchOffersToProjects: this.user.preferences.notificationTypes.offers, - fetchProjectUpdates: this.user.preferences.notificationTypes.projects, - notificationPreferences: { - offers: this.user.preferences.notificationTypes.offers, - projects: this.user.preferences.notificationTypes.projects, - people: this.user.preferences.notificationTypes.people, - items: this.user.preferences.notificationTypes.items - } - }; - } - - /** - * Filter notifications by user preferences - */ - private filterNotificationsByPreferences( - notifications: TimeSafariNotificationType[], - options: NotificationGenerationOptions - ): TimeSafariNotification[] { - if (!this.user) { - return []; - } - - const prefs = this.user.preferences; - const filtered: TimeSafariNotification[] = []; - - for (const notification of notifications) { - // Check if notification type is enabled - if (!this.isNotificationTypeEnabled(notification.type, prefs)) { - continue; - } - - // Check if notification subtype is enabled - if (!this.isNotificationSubtypeEnabled(notification, prefs)) { - continue; - } - - // Check priority filtering - if (options.filterByPriority && !this.meetsPriorityThreshold(notification)) { - continue; - } - - // Apply user preferences - const enhancedNotification: TimeSafariNotification = { - ...notification, - disabled: prefs.frequency.immediate ? false : true, - sound: prefs.sound, - vibration: prefs.vibration, - badge: prefs.badge, - priority: this.mapPriorityFromPreferences(prefs.priority) - }; - - // Add metadata if requested - if (options.includeMetadata) { - enhancedNotification.metadata = { - generatedAt: Date.now(), - platform: 'timesafari', - userDid: this.user.activeDid, - preferencesVersion: 1 - }; - } - - filtered.push(enhancedNotification); - - // Respect max notifications limit - if (filtered.length >= options.maxNotifications) { - break; - } - } - - // Sort by priority and timestamp - filtered.sort((a, b) => { - const priorityOrder: { [key: string]: number } = { high: 3, medium: 2, low: 1 }; - const priorityDiff = priorityOrder[b.notificationPriority] - priorityOrder[a.notificationPriority]; - - if (priorityDiff !== 0) { - return priorityDiff; - } - - return b.timestamp - a.timestamp; - }); - - return filtered; - } - - /** - * Check if notification type is enabled in preferences - */ - private isNotificationTypeEnabled(type: string, prefs: TimeSafariPreferences): boolean { - switch (type) { - case 'offer': - return prefs.notificationTypes.offers; - case 'project': - return prefs.notificationTypes.projects; - case 'person': - return prefs.notificationTypes.people; - case 'item': - return prefs.notificationTypes.items; - default: - return false; - } - } - - /** - * Check if notification subtype is enabled in preferences - */ - private isNotificationSubtypeEnabled( - notification: TimeSafariNotificationType, - prefs: TimeSafariPreferences - ): boolean { - const subtype = notification.subtype; - - switch (notification.type) { - case 'offer': - return (prefs.offerSubtypes as Record)[subtype] || false; - case 'project': - return (prefs.projectSubtypes as Record)[subtype] || false; - case 'person': - return (prefs.peopleSubtypes as Record)[subtype] || false; - case 'item': - return (prefs.itemsSubtypes as Record)[subtype] || false; - default: - return false; - } - } - - /** - * Check if notification meets priority threshold - */ - private meetsPriorityThreshold(notification: TimeSafariNotificationType): boolean { - if (!this.user) return false; - - const requiredPriority = this.user.preferences.priority; - const notificationPriority = notification.notificationPriority; - - const priorityOrder = { high: 3, medium: 2, low: 1 }; - const requiredLevel = priorityOrder[requiredPriority]; - const notificationLevel = priorityOrder[notificationPriority]; - - return notificationLevel >= requiredLevel; - } - - /** - * Map user preference priority to notification priority - */ - private mapPriorityFromPreferences(preferencePriority: 'low' | 'medium' | 'high'): 'low' | 'normal' | 'high' { - switch (preferencePriority) { - case 'low': - return 'low'; - case 'medium': - return 'normal'; - case 'high': - return 'high'; - default: - return 'normal'; - } - } - - /** - * Generate fallback notifications when API fails - */ - private generateFallbackNotifications(): TimeSafariNotification[] { - // Generating fallback notifications - - const fallbackNotifications: TimeSafariNotification[] = [ - { - type: 'offer', - subtype: 'new_to_me', - notificationPriority: 'medium', - timestamp: Date.now(), - disabled: false, - sound: true, - vibration: true, - badge: true, - priority: 'normal', - offer: { - jwtId: 'fallback-offer', - handleId: 'fallback', - issuedAt: new Date().toISOString(), - offeredByDid: 'system', - recipientDid: 'unknown', - unit: 'USD', - amount: 0, - amountGiven: 0, - amountGivenConfirmed: 0, - objectDescription: 'Fallback notification', - validThrough: new Date(Date.now() + 86400000).toISOString(), - fullClaim: {} - }, - metadata: { - generatedAt: Date.now(), - platform: 'timesafari', - fallback: true, - message: 'Unable to fetch real-time updates. Tap to refresh.' - } - } - ]; - - return fallbackNotifications; - } - - /** - * Cache notifications for future use - */ - private cacheNotifications( - notifications: TimeSafariNotificationType[], - timestamp: number - ): void { - if (!this.user) { - throw new Error('User not initialized'); - } - const cacheKey = `notifications_${this.user.activeDid}`; - this.cache.set(cacheKey, { - data: notifications, - timestamp - }); - } - - /** - * Get cached notifications if fresh enough - */ - private getCachedNotifications(): TimeSafariNotificationType[] | null { - if (!this.user) { - throw new Error('User not initialized'); - } - const cacheKey = `notifications_${this.user.activeDid}`; - const cached = this.cache.get(cacheKey); - - if (cached && (Date.now() - cached.timestamp) < 300000) { // 5 minutes - return cached.data; - } - - return null; - } - - /** - * Update user preferences - */ - async updatePreferences(preferences: Partial): Promise { - try { - if (!this.user) { - return false; - } - - this.user.preferences = { ...this.user.preferences, ...preferences }; - - // Clear cache to force refresh with new preferences - this.clearCache(); - - // User preferences updated - return true; - - } catch (error) { - console.error('Error updating preferences:', error); - return false; - } - } - - /** - * Update active DID (for identity changes) - */ - async updateActiveDid(newActiveDid: string): Promise { - try { - // Updating active DID - - // Update security manager - const securityUpdated = await this.securityManager.updateActiveDid(newActiveDid); - if (!securityUpdated) { - console.error('Failed to update security manager'); - return false; - } - - // Generate new JWT token - const token = await this.securityManager.generateJWT({ - scope: 'notifications' - }); - - if (token) { - this.apiClient.setAuthToken(token); - } - - // Clear cache for new identity - this.clearCache(); - - // Update user record - if (this.user) { - this.user.activeDid = newActiveDid; - } - - // Active DID updated successfully - return true; - - } catch (error) { - console.error('Error updating active DID:', error); - return false; - } - } - - /** - * Clear cache - */ - clearCache(): void { - this.cache.clear(); - this.apiClient.clearCache(); - // TimeSafari notification cache cleared - } - - /** - * Get current user configuration - */ - getUser(): TimeSafariUser | undefined { - return this.user; - } - - /** - * Get security manager instance - */ - getSecurityManager(): SecurityManager { - return this.securityManager; - } - - /** - * Get API client instance - */ - getAPIClient(): EndorserAPIClient { - return this.apiClient; - } - - /** - * Check if manager is initialized - */ - isInitialized(): boolean { - return !!this.user && this.securityManager.isInitialized(); - } - - /** - * Reset manager (for user logout/changes) - */ - async reset(): Promise { - try { - await this.securityManager.reset(); - this.clearCache(); - this.user = undefined; - // TimeSafariNotificationManager reset completed - - } catch (error) { - console.error('Error resetting TimeSafariNotificationManager:', error); - } - } - - /** - * Get notification statistics - */ - getStatistics(): { - totalGenerated: number; - cacheSize: number; - activeGenerations: number; - securityOperations: number; - } { - const cacheSize = this.cache.size; - const activeGenerations = this.activeGeneration.size; - const securityOperations = this.securityManager.getOperationHistory().length; - - return { - totalGenerated: 0, // Would track this in real implementation - cacheSize, - activeGenerations, - securityOperations - }; - } -} diff --git a/test-apps/test-api/.gitignore b/test-apps/test-api/.gitignore deleted file mode 100644 index 66cf9ba..0000000 --- a/test-apps/test-api/.gitignore +++ /dev/null @@ -1,152 +0,0 @@ -# Dependencies -node_modules/ -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Coverage directory used by tools like istanbul -coverage/ -*.lcov - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage -.grunt - -# Bower dependency directory -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons -build/Release - -# Dependency directories -jspm_packages/ - -# TypeScript cache -*.tsbuildinfo - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Microbundle cache -.rpt2_cache/ -.rts2_cache_cjs/ -.rts2_cache_es/ -.rts2_cache_umd/ - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -.env -.env.test -.env.local -.env.production - -# parcel-bundler cache -.cache -.parcel-cache - -# Next.js build output -.next - -# Nuxt.js build / generate output -.nuxt -dist - -# Gatsby files -.cache/ -public - -# Storybook build outputs -.out -.storybook-out - -# Temporary folders -tmp/ -temp/ - -# Logs -logs -*.log - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage - -# Grunt intermediate storage -.grunt - -# Bower dependency directory -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons -build/Release - -# Dependency directories -node_modules/ -jspm_packages/ - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -.env - -# IDE files -.vscode/ -.idea/ -*.swp -*.swo -*~ - -# OS generated files -.DS_Store -.DS_Store? -._* -.Spotlight-V100 -.Trashes -ehthumbs.db -Thumbs.db diff --git a/test-apps/test-api/README.md b/test-apps/test-api/README.md deleted file mode 100644 index 80f666a..0000000 --- a/test-apps/test-api/README.md +++ /dev/null @@ -1,282 +0,0 @@ -# Test API Server - -A mock REST API server for testing the Daily Notification Plugin's network functionality, ETag support, and error handling capabilities. - -## Features - -- **Content Endpoints**: Generate mock notification content for different time slots -- **ETag Support**: Full HTTP caching with conditional requests (304 Not Modified) -- **Error Simulation**: Test various error scenarios (timeout, server error, rate limiting) -- **Metrics**: Monitor API usage and performance -- **CORS Enabled**: Cross-origin requests supported for web testing - -## Quick Start - -```bash -# Install dependencies -npm install - -# Start server -npm start - -# Development mode with auto-restart -npm run dev -``` - -## API Endpoints - -### Health Check -```http -GET /health -``` - -**Response:** -```json -{ - "status": "healthy", - "timestamp": 1703123456789, - "version": "1.0.0", - "endpoints": { - "content": "/api/content/:slotId", - "health": "/health", - "metrics": "/api/metrics", - "error": "/api/error/:type" - } -} -``` - -### Get Notification Content -```http -GET /api/content/:slotId -``` - -**Parameters:** -- `slotId`: Slot identifier in format `slot-HH:MM` (e.g., `slot-08:00`) - -**Headers:** -- `If-None-Match`: ETag for conditional requests - -**Response (200 OK):** -```json -{ - "id": "abc12345", - "slotId": "slot-08:00", - "title": "Daily Update - 08:00", - "body": "Your personalized content for 08:00. Content ID: abc12345", - "timestamp": 1703123456789, - "priority": "high", - "category": "daily", - "actions": [ - { "id": "view", "title": "View Details" }, - { "id": "dismiss", "title": "Dismiss" } - ], - "metadata": { - "source": "test-api", - "version": "1.0.0", - "generated": "2023-12-21T08:00:00.000Z" - } -} -``` - -**Response (304 Not Modified):** -When `If-None-Match` header matches current ETag. - -### Update Content -```http -PUT /api/content/:slotId -``` - -**Body:** -```json -{ - "content": { - "title": "Custom Title", - "body": "Custom body content" - } -} -``` - -### Clear All Content -```http -DELETE /api/content -``` - -### Simulate Errors -```http -GET /api/error/:type -``` - -**Error Types:** -- `timeout` - Simulates request timeout (15 seconds) -- `server-error` - Returns 500 Internal Server Error -- `not-found` - Returns 404 Not Found -- `rate-limit` - Returns 429 Rate Limit Exceeded -- `unauthorized` - Returns 401 Unauthorized - -### API Metrics -```http -GET /api/metrics -``` - -**Response:** -```json -{ - "timestamp": 1703123456789, - "contentStore": { - "size": 5, - "slots": ["slot-08:00", "slot-12:00", "slot-18:00"] - }, - "etagStore": { - "size": 5, - "etags": [["slot-08:00", "\"abc123\""]] - }, - "uptime": 3600, - "memory": { - "rss": 50331648, - "heapTotal": 20971520, - "heapUsed": 15728640, - "external": 1048576 - } -} -``` - -## Usage Examples - -### Basic Content Fetch -```bash -curl http://localhost:3001/api/content/slot-08:00 -``` - -### ETag Conditional Request -```bash -# First request -curl -v http://localhost:3001/api/content/slot-08:00 - -# Second request with ETag (should return 304) -curl -v -H "If-None-Match: \"abc123\"" http://localhost:3001/api/content/slot-08:00 -``` - -### Error Testing -```bash -# Test timeout -curl http://localhost:3001/api/error/timeout - -# Test server error -curl http://localhost:3001/api/error/server-error - -# Test rate limiting -curl http://localhost:3001/api/error/rate-limit -``` - -## Integration with Test Apps - -### Android Test App -```typescript -// In your Android test app -const API_BASE_URL = 'http://10.0.2.2:3001'; // Android emulator localhost - -const fetchContent = async (slotId: string) => { - const response = await fetch(`${API_BASE_URL}/api/content/${slotId}`); - return response.json(); -}; -``` - -### iOS Test App -```typescript -// In your iOS test app -const API_BASE_URL = 'http://localhost:3001'; // iOS simulator localhost - -const fetchContent = async (slotId: string) => { - const response = await fetch(`${API_BASE_URL}/api/content/${slotId}`); - return response.json(); -}; -``` - -### Electron Test App -```typescript -// In your Electron test app -const API_BASE_URL = 'http://localhost:3001'; - -const fetchContent = async (slotId: string) => { - const response = await fetch(`${API_BASE_URL}/api/content/${slotId}`); - return response.json(); -}; -``` - -## Configuration - -### Environment Variables -- `PORT`: Server port (default: 3001) -- `NODE_ENV`: Environment mode (development/production) - -### CORS Configuration -The server is configured to allow cross-origin requests from any origin for testing purposes. - -## Testing Scenarios - -### 1. Basic Content Fetching -- Test successful content retrieval -- Verify content structure and format -- Check timestamp accuracy - -### 2. ETag Caching -- Test conditional requests with `If-None-Match` -- Verify 304 Not Modified responses -- Test cache invalidation - -### 3. Error Handling -- Test timeout scenarios -- Test server error responses -- Test rate limiting behavior -- Test network failure simulation - -### 4. Performance Testing -- Test concurrent requests -- Monitor memory usage -- Test long-running scenarios - -## Development - -### Running in Development Mode -```bash -npm run dev -``` - -This uses `nodemon` for automatic server restart on file changes. - -### Adding New Endpoints -1. Add route handler in `server.js` -2. Update health check endpoint list -3. Add documentation to this README -4. Add test cases if applicable - -### Testing -```bash -npm test -``` - -## Troubleshooting - -### Common Issues - -1. **Port Already in Use** - ```bash - # Kill process using port 3001 - lsof -ti:3001 | xargs kill -9 - ``` - -2. **CORS Issues** - - Server is configured to allow all origins - - Check browser console for CORS errors - -3. **Network Connectivity** - - Android emulator: Use `10.0.2.2` instead of `localhost` - - iOS simulator: Use `localhost` or `127.0.0.1` - - Physical devices: Use your computer's IP address - -### Logs -The server logs all requests with timestamps and response codes for debugging. - -## License - -MIT License - See LICENSE file for details. diff --git a/test-apps/test-api/SETUP.md b/test-apps/test-api/SETUP.md deleted file mode 100644 index 06a6b85..0000000 --- a/test-apps/test-api/SETUP.md +++ /dev/null @@ -1,76 +0,0 @@ -# Test API Server Setup - -## Overview - -The Test API Server provides mock endpoints for testing the Daily Notification Plugin's network functionality, including ETag support, error handling, and content fetching. - -## Quick Setup - -```bash -# Navigate to test-api directory -cd test-apps/test-api - -# Install dependencies -npm install - -# Start server -npm start -``` - -## Integration with Test Apps - -### Update Test App Configuration - -Add the API base URL to your test app configuration: - -```typescript -// In your test app's config -const API_CONFIG = { - baseUrl: 'http://localhost:3001', // Adjust for platform - endpoints: { - content: '/api/content', - health: '/health', - error: '/api/error', - metrics: '/api/metrics' - } -}; -``` - -### Platform-Specific URLs - -- **Web/Electron**: `http://localhost:3001` -- **Android Emulator**: `http://10.0.2.2:3001` -- **iOS Simulator**: `http://localhost:3001` -- **Physical Devices**: `http://[YOUR_IP]:3001` - -## Testing Workflow - -1. **Start API Server**: `npm start` in `test-apps/test-api/` -2. **Start Test App**: Run your platform-specific test app -3. **Test Scenarios**: Use the test app to validate plugin functionality -4. **Monitor API**: Check `/api/metrics` for usage statistics - -## Available Test Scenarios - -### Content Fetching -- Basic content retrieval -- ETag conditional requests -- Content updates and caching - -### Error Handling -- Network timeouts -- Server errors -- Rate limiting -- Authentication failures - -### Performance Testing -- Concurrent requests -- Memory usage monitoring -- Long-running scenarios - -## Next Steps - -1. Start the API server -2. Configure your test apps to use the API -3. Run through the test scenarios -4. Validate plugin functionality across platforms diff --git a/test-apps/test-api/client.ts b/test-apps/test-api/client.ts deleted file mode 100644 index 8842844..0000000 --- a/test-apps/test-api/client.ts +++ /dev/null @@ -1,305 +0,0 @@ -/** - * Test API Client for Daily Notification Plugin - * - * Demonstrates how to integrate with the test API server - * for validating plugin functionality. - * - * @author Matthew Raymer - * @version 1.0.0 - */ - -export interface TestAPIConfig { - baseUrl: string; - timeout: number; -} - -export interface NotificationContent { - id: string; - slotId: string; - title: string; - body: string; - timestamp: number; - priority: string; - category: string; - actions: Array<{ id: string; title: string }>; - metadata: { - source: string; - version: string; - generated: string; - }; -} - -export interface APIResponse { - data?: T; - error?: string; - status: number; - etag?: string; - fromCache: boolean; -} - -export class TestAPIClient { - private config: TestAPIConfig; - private etagCache = new Map(); - - constructor(config: TestAPIConfig) { - this.config = config; - } - - /** - * Fetch notification content for a specific slot - * @param slotId - Slot identifier (e.g., 'slot-08:00') - * @returns Promise> - */ - async fetchContent(slotId: string): Promise> { - const url = `${this.config.baseUrl}/api/content/${slotId}`; - const headers: Record = {}; - - // Add ETag for conditional request if we have cached content - const cachedETag = this.etagCache.get(slotId); - if (cachedETag) { - headers['If-None-Match'] = cachedETag; - } - - try { - const response = await fetch(url, { - method: 'GET', - headers, - signal: AbortSignal.timeout(this.config.timeout) - }); - - const etag = response.headers.get('ETag'); - const fromCache = response.status === 304; - - if (fromCache) { - return { - status: response.status, - fromCache: true, - etag: cachedETag - }; - } - - if (!response.ok) { - throw new Error(`HTTP ${response.status}: ${response.statusText}`); - } - - const data = await response.json(); - - // Cache ETag for future conditional requests - if (etag) { - this.etagCache.set(slotId, etag); - } - - return { - data, - status: response.status, - etag, - fromCache: false - }; - - } catch (error) { - return { - error: error instanceof Error ? error.message : 'Unknown error', - status: 0, - fromCache: false - }; - } - } - - /** - * Test error scenarios - * @param errorType - Type of error to simulate - * @returns Promise> - */ - async testError(errorType: string): Promise> { - const url = `${this.config.baseUrl}/api/error/${errorType}`; - - try { - const response = await fetch(url, { - method: 'GET', - signal: AbortSignal.timeout(this.config.timeout) - }); - - const data = await response.json(); - - return { - data, - status: response.status, - fromCache: false - }; - - } catch (error) { - return { - error: error instanceof Error ? error.message : 'Unknown error', - status: 0, - fromCache: false - }; - } - } - - /** - * Get API health status - * @returns Promise> - */ - async getHealth(): Promise> { - const url = `${this.config.baseUrl}/health`; - - try { - const response = await fetch(url, { - method: 'GET', - signal: AbortSignal.timeout(this.config.timeout) - }); - - const data = await response.json(); - - return { - data, - status: response.status, - fromCache: false - }; - - } catch (error) { - return { - error: error instanceof Error ? error.message : 'Unknown error', - status: 0, - fromCache: false - }; - } - } - - /** - * Get API metrics - * @returns Promise> - */ - async getMetrics(): Promise> { - const url = `${this.config.baseUrl}/api/metrics`; - - try { - const response = await fetch(url, { - method: 'GET', - signal: AbortSignal.timeout(this.config.timeout) - }); - - const data = await response.json(); - - return { - data, - status: response.status, - fromCache: false - }; - - } catch (error) { - return { - error: error instanceof Error ? error.message : 'Unknown error', - status: 0, - fromCache: false - }; - } - } - - /** - * Clear ETag cache - */ - clearCache(): void { - this.etagCache.clear(); - } - - /** - * Get cached ETags - * @returns Map of slotId to ETag - */ - getCachedETags(): Map { - return new Map(this.etagCache); - } -} - -/** - * Platform-specific API configuration - */ -export const getAPIConfig = (): TestAPIConfig => { - // Detect platform and set appropriate base URL - if (typeof window !== 'undefined') { - // Web/Electron - return { - baseUrl: 'http://localhost:3001', - timeout: 12000 // 12 seconds - }; - } - - // Default configuration - return { - baseUrl: 'http://localhost:3001', - timeout: 12000 - }; -}; - -/** - * Usage examples for test apps - */ -export const TestAPIExamples = { - /** - * Basic content fetching example - */ - async basicFetch(): Promise { - const client = new TestAPIClient(getAPIConfig()); - - // console.log('Testing basic content fetch...'); - const result = await client.fetchContent('slot-08:00'); - - if (result.error) { - // console.error('Error:', result.error); - } else { - // console.log('Success:', result.data); - // console.log('ETag:', result.etag); - // console.log('From cache:', result.fromCache); - } - }, - - /** - * ETag caching example - */ - async etagCaching(): Promise { - // const client = new TestAPIClient(getAPIConfig()); - - // console.log('Testing ETag caching...'); - - // First request - // const result1 = await client.fetchContent('slot-08:00'); - // console.log('First request:', result1.fromCache ? 'From cache' : 'Fresh content'); - - // Second request (should be from cache) - // const result2 = await client.fetchContent('slot-08:00'); - // console.log('Second request:', result2.fromCache ? 'From cache' : 'Fresh content'); - }, - - /** - * Error handling example - */ - async errorHandling(): Promise { - // const client = new TestAPIClient(getAPIConfig()); - - // console.log('Testing error handling...'); - - // const errorTypes = ['timeout', 'server-error', 'not-found', 'rate-limit']; - - // for (const errorType of errorTypes) { - // const result = await client.testError(errorType); - // console.log(`${errorType}:`, result.status, result.error || 'Success'); - // } - }, - - /** - * Health check example - */ - async healthCheck(): Promise { - const client = new TestAPIClient(getAPIConfig()); - - // console.log('Testing health check...'); - const result = await client.getHealth(); - - if (result.error) { - // console.error('Health check failed:', result.error); - } else { - // console.log('API is healthy:', result.data); - } - } -}; diff --git a/test-apps/test-api/package-lock.json b/test-apps/test-api/package-lock.json deleted file mode 100644 index 1d0b166..0000000 --- a/test-apps/test-api/package-lock.json +++ /dev/null @@ -1,4799 +0,0 @@ -{ - "name": "daily-notification-test-api", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "daily-notification-test-api", - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "cors": "^2.8.5", - "express": "^4.18.2" - }, - "devDependencies": { - "jest": "^29.7.0", - "node-fetch": "^2.7.0", - "nodemon": "^3.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.4.tgz", - "integrity": "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", - "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.3", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.28.3", - "@babel/helpers": "^7.28.4", - "@babel/parser": "^7.28.4", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.4", - "@babel/types": "^7.28.4", - "@jridgewell/remapping": "^2.3.5", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@babel/core/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/@babel/generator": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", - "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.28.3", - "@babel/types": "^7.28.2", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.27.2", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", - "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.28.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", - "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", - "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", - "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.4" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", - "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", - "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", - "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz", - "integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.3", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.4", - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4", - "debug": "^4.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@babel/traverse/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/@babel/types": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", - "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/console": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/core": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", - "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/reporters": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-resolve-dependencies": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "jest-watcher": "^29.7.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "jest-get-type": "^29.6.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/reporters": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", - "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/source-map": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/test-result": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/test-sequencer": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", - "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.30", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz", - "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.0" - } - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", - "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", - "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.2" - } - }, - "node_modules/@types/graceful-fs": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", - "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", - "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", - "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/@types/node": { - "version": "24.3.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.1.tgz", - "integrity": "sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~7.10.0" - } - }, - "node_modules/@types/stack-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/yargs": { - "version": "17.0.33", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", - "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "license": "MIT", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "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/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "license": "MIT" - }, - "node_modules/babel-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.0" - } - }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-jest-hoist": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", - "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", - "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-import-attributes": "^7.24.7", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5" - }, - "peerDependencies": { - "@babel/core": "^7.0.0 || ^8.0.0-0" - } - }, - "node_modules/babel-preset-jest": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", - "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", - "dev": true, - "license": "MIT", - "dependencies": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.25.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.4.tgz", - "integrity": "sha512-4jYpcjabC606xJ3kw2QwGEZKX0Aw7sgQdZCvIK9dhVSPh76BKo+C+btT1RRofH7B+8iNpEbgGNVWiLki5q93yg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "caniuse-lite": "^1.0.30001737", - "electron-to-chromium": "^1.5.211", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.3" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "node-int64": "^0.4.0" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001741", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001741.tgz", - "integrity": "sha512-QGUGitqsc8ARjLdgAfxETDhRbJ0REsP6O3I96TAth/mVjh2cYzN2u+3AzPP3aVSm2FehEItaJw1xd+IGBXWeSw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cjs-module-lexer": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", - "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" - } - }, - "node_modules/collect-v8-coverage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", - "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/color-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/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/cookie": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", - "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "license": "MIT" - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "license": "MIT", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/create-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", - "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "prompts": "^2.0.1" - }, - "bin": { - "create-jest": "bin/create-jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/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/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/dedent": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.0.tgz", - "integrity": "sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" - }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "optional": true - } - } - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "license": "MIT", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "license": "MIT" - }, - "node_modules/electron-to-chromium": { - "version": "1.5.215", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.215.tgz", - "integrity": "sha512-TIvGp57UpeNetj/wV/xpFNpWGb0b/ROw372lHPx5Aafx02gjTBtWnEEcaSX3W2dLM3OSdGGyHX/cHl01JQsLaQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "license": "MIT" - }, - "node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/express": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", - "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", - "license": "MIT", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.12", - "proxy-addr": "~2.0.7", - "qs": "6.13.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/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/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "bser": "2.1.1" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true, - "license": "ISC" - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true, - "license": "MIT" - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", - "dev": true, - "license": "ISC" - }, - "node_modules/import-local": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", - "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", - "dev": true, - "license": "MIT", - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "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-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", - "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/core": "^7.23.9", - "@babel/parser": "^7.23.9", - "@istanbuljs/schema": "^0.1.3", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-source-maps/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/istanbul-lib-source-maps/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/istanbul-reports": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", - "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", - "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/core": "^29.7.0", - "@jest/types": "^29.6.3", - "import-local": "^3.0.2", - "jest-cli": "^29.7.0" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-changed-files": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", - "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", - "dev": true, - "license": "MIT", - "dependencies": { - "execa": "^5.0.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-circus": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", - "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^1.0.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.7.0", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0", - "pretty-format": "^29.7.0", - "pure-rand": "^6.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-cli": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", - "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/core": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "create-jest": "^29.7.0", - "exit": "^0.1.2", - "import-local": "^3.0.2", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "yargs": "^17.3.1" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-config": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", - "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-jest": "^29.7.0", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-docblock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", - "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "detect-newline": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-each": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", - "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "jest-util": "^29.7.0", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-environment-node": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", - "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" - } - }, - "node_modules/jest-leak-detector": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", - "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", - "dev": true, - "license": "MIT", - "dependencies": { - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-matcher-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", - "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-message-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-mock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", - "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" - }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } - } - }, - "node_modules/jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-resolve": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", - "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-resolve-dependencies": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", - "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", - "dev": true, - "license": "MIT", - "dependencies": { - "jest-regex-util": "^29.6.3", - "jest-snapshot": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runner": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", - "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/environment": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-leak-detector": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-resolve": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-util": "^29.7.0", - "jest-watcher": "^29.7.0", - "jest-worker": "^29.7.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runtime": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", - "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/globals": "^29.7.0", - "@jest/source-map": "^29.6.3", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-snapshot": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", - "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "natural-compare": "^1.4.0", - "pretty-format": "^29.7.0", - "semver": "^7.5.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-validate": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-validate/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-watcher": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", - "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.7.0", - "string-length": "^4.0.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true, - "license": "MIT" - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true, - "license": "MIT" - }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "tmpl": "1.0.5" - } - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true, - "license": "MIT" - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "license": "MIT" - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true, - "license": "MIT" - }, - "node_modules/node-releases": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.20.tgz", - "integrity": "sha512-7gK6zSXEH6neM212JgfYFXe+GmZQM+fia5SsusuBIUgnPheLFBmIPhtFoAQRj8/7wASYQnbDlHPVwY0BefoFgA==", - "dev": true, - "license": "MIT" - }, - "node_modules/nodemon": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.10.tgz", - "integrity": "sha512-WDjw3pJ0/0jMFmyNDp3gvY2YizjLmmOUQo6DEBY+JgdvW/yQ9mEeSw6H5ythl5Ny2ytb7f9C2nIbjSxMNzbJXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chokidar": "^3.5.2", - "debug": "^4", - "ignore-by-default": "^1.0.1", - "minimatch": "^3.1.2", - "pstree.remy": "^1.1.8", - "semver": "^7.5.3", - "simple-update-notifier": "^2.0.0", - "supports-color": "^5.5.0", - "touch": "^3.1.0", - "undefsafe": "^2.0.5" - }, - "bin": { - "nodemon": "bin/nodemon.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nodemon" - } - }, - "node_modules/nodemon/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/nodemon/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/nodemon/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/nodemon/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/nodemon/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-locate/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "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-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", - "license": "MIT" - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pirates": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", - "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "license": "MIT", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/pstree.remy": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", - "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", - "dev": true, - "license": "MIT" - }, - "node_modules/pure-rand": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", - "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ], - "license": "MIT" - }, - "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true, - "license": "MIT" - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.16.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve.exports": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", - "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "license": "MIT" - }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", - "license": "MIT", - "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "license": "ISC" - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/simple-update-notifier": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", - "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/simple-update-notifier/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true, - "license": "MIT" - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/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": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/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/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "license": "ISC", - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/touch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", - "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", - "dev": true, - "license": "ISC", - "bin": { - "nodetouch": "bin/nodetouch.js" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true, - "license": "MIT" - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "license": "MIT", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/undefsafe": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", - "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", - "dev": true, - "license": "MIT" - }, - "node_modules/undici-types": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", - "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==", - "dev": true, - "license": "MIT" - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/v8-to-istanbul": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", - "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", - "dev": true, - "license": "ISC", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "makeerror": "1.0.12" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "dev": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "license": "ISC" - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/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/test-apps/test-api/package.json b/test-apps/test-api/package.json deleted file mode 100644 index 3b08a53..0000000 --- a/test-apps/test-api/package.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "daily-notification-test-api", - "version": "1.0.0", - "description": "Test API server for Daily Notification Plugin validation", - "main": "server.js", - "scripts": { - "start": "node server.js", - "dev": "nodemon server.js", - "test": "jest", - "demo": "node test-demo.js" - }, - "keywords": [ - "test", - "api", - "notification", - "capacitor", - "plugin" - ], - "author": "Matthew Raymer", - "license": "MIT", - "dependencies": { - "express": "^4.18.2", - "cors": "^2.8.5" - }, - "devDependencies": { - "nodemon": "^3.0.1", - "jest": "^29.7.0", - "node-fetch": "^2.7.0" - }, - "engines": { - "node": ">=18.0.0" - } -} diff --git a/test-apps/test-api/server.js b/test-apps/test-api/server.js deleted file mode 100644 index b6ec268..0000000 --- a/test-apps/test-api/server.js +++ /dev/null @@ -1,535 +0,0 @@ -#!/usr/bin/env node - -/** - * Test API Server for TimeSafari Daily Notification Plugin - * - * Simulates Endorser.ch API endpoints for testing the plugin's - * network fetching, pagination, and TimeSafari-specific functionality. - * - * @author Matthew Raymer - * @version 2.0.0 - */ - -const express = require('express'); -const cors = require('cors'); -const crypto = require('crypto'); - -const app = express(); -const PORT = process.env.PORT || 3001; - -// Phase 4: JWT authentication middleware for testing SecurityManager -function verifyJWT(req, res, next) { - const authHeader = req.headers.authorization; - - if (!authHeader || !authHeader.startsWith('Bearer ')) { - return res.status(401).json({ - error: 'Missing or invalid Authorization header', - expected: 'Bearer ' - }); - } - - const token = authHeader.substring(7); // Remove 'Bearer ' prefix - - // Simple JWT validation for testing (in production, use proper JWT library) - try { - const parts = token.split('.'); - if (parts.length !== 3) { - throw new Error('Invalid JWT format'); - } - - // Decode payload (base64url) - const payload = JSON.parse(Buffer.from(parts[1], 'base64url').toString()); - - // Check expiration - if (payload.exp && payload.exp < Math.floor(Date.now() / 1000)) { - return res.status(401).json({ - error: 'JWT token expired', - expiredAt: new Date(payload.exp * 1000).toISOString() - }); - } - - // Add decoded claims to request for use in endpoints - req.jwtClaims = payload; - req.activeDid = payload.iss; // Assuming 'iss' contains the active DID - - console.log(`✅ JWT verified for DID: ${req.activeDid}`); - next(); - - } catch (error) { - console.log(`❌ JWT verification failed: ${error.message}`); - return res.status(401).json({ - error: 'Invalid JWT token', - details: error.message - }); - } -} - -// Middleware -app.use(cors()); -app.use(express.json()); - -// In-memory storage for testing -let contentStore = new Map(); -let etagStore = new Map(); -let offersStore = new Map(); -let projectsStore = new Map(); - -/** - * Generate mock offer data for TimeSafari testing - * @param {string} recipientDid - DID of the recipient - * @param {string} afterId - JWT ID for pagination - * @returns {Object} Mock offer data - */ -function generateMockOffers(recipientDid, afterId) { - const offers = []; - const offerCount = Math.floor(Math.random() * 5) + 1; // 1-5 offers - - for (let i = 0; i < offerCount; i++) { - const jwtId = `01HSE3R9MAC0FT3P3KZ382TWV${7 + i}`; - const handleId = `offer-${crypto.randomUUID().substring(0, 8)}`; - - offers.push({ - jwtId: jwtId, - handleId: handleId, - issuedAt: new Date().toISOString(), - offeredByDid: `did:example:offerer${i + 1}`, - recipientDid: recipientDid, - unit: 'USD', - amount: Math.floor(Math.random() * 5000) + 500, - amountGiven: Math.floor(Math.random() * 2000) + 200, - amountGivenConfirmed: Math.floor(Math.random() * 1000) + 100, - objectDescription: `Community service offer ${i + 1}`, - validThrough: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(), - fullClaim: { - type: 'Offer', - issuer: `did:example:offerer${i + 1}`, - recipient: recipientDid, - object: { - description: `Community service offer ${i + 1}`, - amount: Math.floor(Math.random() * 5000) + 500, - unit: 'USD' - } - } - }); - } - - return { - data: offers, - hitLimit: offers.length >= 3 // Simulate hit limit - }; -} - -/** - * Generate mock project data for TimeSafari testing - * @param {Array} planIds - Array of plan IDs - * @param {string} afterId - JWT ID for pagination - * @returns {Object} Mock project data - */ -function generateMockProjects(planIds, afterId) { - const projects = []; - - planIds.forEach((planId, index) => { - const jwtId = `01HSE3R9MAC0FT3P3KZ382TWV${8 + index}`; - - projects.push({ - plan: { - jwtId: jwtId, - handleId: planId, - name: `Community Project ${index + 1}`, - description: `Description for ${planId}`, - issuerDid: `did:example:issuer${index + 1}`, - agentDid: `did:example:agent${index + 1}`, - startTime: new Date().toISOString(), - endTime: new Date(Date.now() + 90 * 24 * 60 * 60 * 1000).toISOString(), - locLat: 40.7128 + (Math.random() - 0.5) * 0.1, - locLon: -74.0060 + (Math.random() - 0.5) * 0.1, - url: `https://timesafari.com/projects/${planId}`, - category: 'community', - status: 'active' - }, - wrappedClaimBefore: null // Simulate no previous claim - }); - }); - - return { - data: projects, - hitLimit: projects.length >= 2 // Simulate hit limit - }; -} - -/** - * Generate mock notification bundle for TimeSafari - * @param {Object} params - Request parameters - * @returns {Object} Mock notification bundle - */ -function generateNotificationBundle(params) { - const { userDid, starredPlanIds, lastKnownOfferId, lastKnownPlanId } = params; - - return { - offersToPerson: generateMockOffers(userDid, lastKnownOfferId), - offersToProjects: { - data: [], - hitLimit: false - }, - starredChanges: generateMockProjects(starredPlanIds, lastKnownPlanId), - timestamp: new Date().toISOString(), - bundleId: crypto.randomUUID() - }; -} - -// Routes - -/** - * Health check endpoint - */ -app.get('/health', (req, res) => { - res.json({ - status: 'healthy', - timestamp: Date.now(), - version: '2.0.0', - service: 'TimeSafari Test API', - endpoints: { - health: '/health', - offers: '/api/v2/report/offers', - offersToPlans: '/api/v2/report/offersToPlansOwnedByMe', - plansLastUpdated: '/api/v2/report/plansLastUpdatedBetween', - notificationsBundle: '/api/v2/report/notifications/bundle', - analytics: '/api/analytics/community-events', - metrics: '/api/metrics' - } - }); -}); - -/** - * Endorser.ch API: Get offers to person - * Phase 4: Requires JWT authentication - */ -app.get('/api/v2/report/offers', verifyJWT, (req, res) => { - const { recipientId, afterId } = req.query; - - console.log(`[${new Date().toISOString()}] GET /api/v2/report/offers`); - console.log(` JWT DID: ${req.activeDid}, recipientId: ${recipientId}, afterId: ${afterId || 'none'}`); - - if (!recipientId) { - return res.status(400).json({ - error: 'recipientId parameter is required' - }); - } - - // Phase 4: Validate that JWT DID matches recipientId for security - if (req.activeDid !== recipientId) { - console.log(` ❌ JWT DID mismatch: ${req.activeDid} != ${recipientId}`); - return res.status(403).json({ - error: 'JWT DID does not match recipientId', - jwtDid: req.activeDid, - requestedRecipientId: recipientId - }); - } - - const offers = generateMockOffers(recipientId, afterId); - - console.log(` → 200 OK (${offers.data.length} offers, hitLimit: ${offers.hitLimit})`); - res.json(offers); -}); - -/** - * Endorser.ch API: Get offers to user's projects - * Phase 4: Requires JWT authentication - */ -app.get('/api/v2/report/offersToPlansOwnedByMe', verifyJWT, (req, res) => { - const { afterId } = req.query; - - console.log(`[${new Date().toISOString()}] GET /api/v2/report/offersToPlansOwnedByMe`); - console.log(` JWT DID: ${req.activeDid}, afterId: ${afterId || 'none'}`); - - const offers = { - data: [], // Simulate no offers to user's projects - hitLimit: false - }; - - console.log(` → 200 OK (${offers.data.length} offers, hitLimit: ${offers.hitLimit})`); - res.json(offers); -}); - -/** - * Endorser.ch API: Get changes to starred projects - * Phase 4: Requires JWT authentication - */ -app.post('/api/v2/report/plansLastUpdatedBetween', verifyJWT, (req, res) => { - const { planIds, afterId } = req.body; - - console.log(`[${new Date().toISOString()}] POST /api/v2/report/plansLastUpdatedBetween`); - console.log(` JWT DID: ${req.activeDid}, planIds: ${JSON.stringify(planIds)}, afterId: ${afterId || 'none'}`); - - if (!planIds || !Array.isArray(planIds)) { - return res.status(400).json({ - error: 'planIds array is required' - }); - } - - const projects = generateMockProjects(planIds, afterId); - - console.log(` → 200 OK (${projects.data.length} projects, hitLimit: ${projects.hitLimit})`); - res.json(projects); -}); - -/** - * TimeSafari API: Get notification bundle - */ -app.get('/api/v2/report/notifications/bundle', (req, res) => { - const { userDid, starredPlanIds, lastKnownOfferId, lastKnownPlanId } = req.query; - - console.log(`[${new Date().toISOString()}] GET /api/v2/report/notifications/bundle`); - console.log(` userDid: ${userDid}, starredPlanIds: ${starredPlanIds}`); - - if (!userDid) { - return res.status(400).json({ - error: 'userDid parameter is required' - }); - } - - const bundle = generateNotificationBundle({ - userDid, - starredPlanIds: starredPlanIds ? JSON.parse(starredPlanIds) : [], - lastKnownOfferId, - lastKnownPlanId - }); - - console.log(` → 200 OK (bundle generated)`); - res.json(bundle); -}); - -/** - * TimeSafari Analytics: Community events - */ -app.post('/api/analytics/community-events', (req, res) => { - const { client_id, events } = req.body; - - console.log(`[${new Date().toISOString()}] POST /api/analytics/community-events`); - console.log(` client_id: ${client_id}, events: ${events?.length || 0}`); - - // Simulate analytics processing - res.json({ - status: 'success', - processed: events?.length || 0, - timestamp: new Date().toISOString() - }); -}); - -/** - * Legacy content endpoint (for backward compatibility) - */ -app.get('/api/content/:slotId', (req, res) => { - const { slotId } = req.params; - const ifNoneMatch = req.headers['if-none-match']; - const timestamp = Date.now(); - - console.log(`[${new Date().toISOString()}] GET /api/content/${slotId}`); - console.log(` If-None-Match: ${ifNoneMatch || 'none'}`); - - // Validate slotId format - if (!slotId || !slotId.match(/^slot-\d{2}:\d{2}$/)) { - return res.status(400).json({ - error: 'Invalid slotId format. Expected: slot-HH:MM', - provided: slotId - }); - } - - // Check if we have stored content - const stored = contentStore.get(slotId); - const etag = etagStore.get(slotId); - - if (stored && etag && ifNoneMatch === etag) { - // Content hasn't changed, return 304 Not Modified - console.log(` → 304 Not Modified (ETag match)`); - return res.status(304).end(); - } - - // Generate new content - const content = { - id: crypto.randomUUID().substring(0, 8), - slotId: slotId, - title: `TimeSafari Community Update - ${slotId.split('-')[1]}`, - body: `Your personalized TimeSafari content for ${slotId.split('-')[1]}`, - timestamp: timestamp, - priority: 'high', - category: 'community', - actions: [ - { id: 'view_offers', title: 'View Offers' }, - { id: 'view_projects', title: 'See Projects' }, - { id: 'view_people', title: 'Check People' }, - { id: 'view_items', title: 'Browse Items' }, - { id: 'dismiss', title: 'Dismiss' } - ], - metadata: { - source: 'timesafari-test-api', - version: '2.0.0', - generated: new Date(timestamp).toISOString() - } - }; - - const newEtag = `"${crypto.createHash('md5').update(JSON.stringify(content)).digest('hex')}"`; - - // Store for future ETag checks - contentStore.set(slotId, content); - etagStore.set(slotId, newEtag); - - // Set ETag header - res.set('ETag', newEtag); - res.set('Cache-Control', 'no-cache'); - res.set('Last-Modified', new Date(timestamp).toUTCString()); - - console.log(` → 200 OK (new content, ETag: ${newEtag})`); - res.json(content); -}); - -/** - * API metrics endpoint - */ -app.get('/api/metrics', (req, res) => { - const metrics = { - timestamp: Date.now(), - service: 'TimeSafari Test API', - version: '2.0.0', - contentStore: { - size: contentStore.size, - slots: Array.from(contentStore.keys()) - }, - etagStore: { - size: etagStore.size, - etags: Array.from(etagStore.entries()) - }, - uptime: process.uptime(), - memory: process.memoryUsage(), - endpoints: { - total: 8, - active: 8, - health: '/health', - endorser: { - offers: '/api/v2/report/offers', - offersToPlans: '/api/v2/report/offersToPlansOwnedByMe', - plansLastUpdated: '/api/v2/report/plansLastUpdatedBetween' - }, - timesafari: { - notificationsBundle: '/api/v2/report/notifications/bundle', - analytics: '/api/analytics/community-events' - } - } - }; - - res.json(metrics); -}); - -/** - * Clear stored content (for testing) - */ -app.delete('/api/content', (req, res) => { - contentStore.clear(); - etagStore.clear(); - - res.json({ - message: 'All stored content cleared', - timestamp: Date.now() - }); -}); - -// Error handling middleware -app.use((err, req, res, next) => { - console.error(`[${new Date().toISOString()}] Error:`, err); - res.status(500).json({ - error: 'Internal server error', - message: err.message, - timestamp: Date.now() - }); -}); - -// 404 handler -app.use((req, res) => { - res.status(404).json({ - error: 'Endpoint not found', - path: req.path, - method: req.method, - timestamp: Date.now() - }); -}); - -/** - * Phase 4: JWT validation test endpoint - * Allows testing SecurityManager JWT generation and verification - */ -app.get('/api/v2/test/jwt-validation', verifyJWT, (req, res) => { - console.log(`[${new Date().toISOString()}] GET /api/v2/test/jwt-validation`); - console.log(` JWT DID: ${req.activeDid}`); - - res.json({ - success: true, - message: 'JWT validation successful', - jwtClaims: req.jwtClaims, - activeDid: req.activeDid, - timestamp: new Date().toISOString() - }); -}); - -/** - * Phase 4: Security test endpoint (no auth required) - * For testing SecurityManager initialization - */ -app.get('/api/v2/test/security-info', (req, res) => { - console.log(`[${new Date().toISOString()}] GET /api/v2/test/security-info`); - - res.json({ - securityInfo: { - jwtRequired: true, - supportedAlgorithms: ['HS256', 'ES256K'], - tokenExpiration: '60 minutes', - audience: 'endorser-api', - scope: 'notifications' - }, - testEndpoints: { - jwtValidation: '/api/v2/test/jwt-validation', - offers: '/api/v2/report/offers', - offersToProjects: '/api/v2/report/offersToPlansOwnedByMe', - projectUpdates: '/api/v2/report/plansLastUpdatedBetween' - }, - timestamp: new Date().toISOString() - }); -}); - -// Start server -app.listen(PORT, () => { - console.log(`🚀 TimeSafari Test API Server running on port ${PORT}`); - console.log(`📋 Available endpoints:`); - console.log(` GET /health - Health check`); - console.log(` GET /api/v2/report/offers - Get offers to person (JWT required)`); - console.log(` GET /api/v2/report/offersToPlansOwnedByMe - Get offers to user's projects (JWT required)`); - console.log(` POST /api/v2/report/plansLastUpdatedBetween - Get changes to starred projects (JWT required)`); - console.log(` GET /api/v2/report/notifications/bundle - Get TimeSafari notification bundle`); - console.log(` GET /api/v2/test/jwt-validation - Test JWT validation (JWT required)`); - console.log(` GET /api/v2/test/security-info - Get security configuration info`); - console.log(` POST /api/analytics/community-events - Send community analytics`); - console.log(` GET /api/content/:slotId - Legacy content endpoint`); - console.log(` GET /api/metrics - API metrics`); - console.log(``); - console.log(`🔧 Environment:`); - console.log(` NODE_ENV: ${process.env.NODE_ENV || 'development'}`); - console.log(` PORT: ${PORT}`); - console.log(``); - console.log(`📝 Usage examples:`); - console.log(` curl http://localhost:${PORT}/health`); - console.log(` curl http://localhost:${PORT}/api/v2/test/security-info`); - console.log(` curl -H "Authorization: Bearer " "http://localhost:${PORT}/api/v2/test/jwt-validation"`); - console.log(` curl -H "Authorization: Bearer " "http://localhost:${PORT}/api/v2/report/offers?recipientId=did:example:testuser123&afterId=01HSE3R9MAC0FT3P3KZ382TWV7"`); - console.log(` curl -H "Authorization: Bearer " -X POST http://localhost:${PORT}/api/v2/report/plansLastUpdatedBetween -H "Content-Type: application/json" -d '{"planIds":["plan-123","plan-456"],"afterId":"01HSE3R9MAC0FT3P3KZ382TWV8"}'`); - console.log(` curl "http://localhost:${PORT}/api/v2/report/notifications/bundle?userDid=did:example:testuser123&starredPlanIds=[\"plan-123\",\"plan-456\"]"`); -}); - -// Graceful shutdown -process.on('SIGINT', () => { - console.log('\n🛑 Shutting down TimeSafari Test API Server...'); - process.exit(0); -}); - -process.on('SIGTERM', () => { - console.log('\n🛑 Shutting down TimeSafari Test API Server...'); - process.exit(0); -}); diff --git a/test-apps/test-api/test-demo.js b/test-apps/test-api/test-demo.js deleted file mode 100644 index 2f5fbb4..0000000 --- a/test-apps/test-api/test-demo.js +++ /dev/null @@ -1,294 +0,0 @@ -#!/usr/bin/env node - -/** - * Test API Demo Script - * - * Demonstrates the Test API Server functionality - * and validates all endpoints work correctly. - * - * @author Matthew Raymer - * @version 1.0.0 - */ - -const fetch = require('node-fetch'); - -const API_BASE_URL = 'http://localhost:3001'; - -/** - * Make HTTP request with timeout - * @param {string} url - Request URL - * @param {Object} options - Fetch options - * @returns {Promise} Response data - */ -async function makeRequest(url, options = {}) { - try { - const response = await fetch(url, { - timeout: 10000, - ...options - }); - - const data = await response.json(); - - return { - status: response.status, - data, - headers: Object.fromEntries(response.headers.entries()) - }; - } catch (error) { - return { - status: 0, - error: error.message - }; - } -} - -/** - * Test health endpoint - */ -async function testHealth() { - console.log('🔍 Testing health endpoint...'); - - const result = await makeRequest(`${API_BASE_URL}/health`); - - if (result.error) { - console.error('❌ Health check failed:', result.error); - return false; - } - - console.log('✅ Health check passed'); - console.log(' Status:', result.status); - console.log(' Version:', result.data.version); - console.log(' Endpoints:', Object.keys(result.data.endpoints).length); - - return true; -} - -/** - * Test content fetching - */ -async function testContentFetching() { - console.log('\n📱 Testing content fetching...'); - - const slotId = 'slot-08:00'; - const result = await makeRequest(`${API_BASE_URL}/api/content/${slotId}`); - - if (result.error) { - console.error('❌ Content fetch failed:', result.error); - return false; - } - - console.log('✅ Content fetch passed'); - console.log(' Status:', result.status); - console.log(' Slot ID:', result.data.slotId); - console.log(' Title:', result.data.title); - console.log(' ETag:', result.headers.etag); - - return result.headers.etag; -} - -/** - * Test ETag caching - */ -async function testETagCaching(etag) { - console.log('\n🔄 Testing ETag caching...'); - - const slotId = 'slot-08:00'; - const result = await makeRequest(`${API_BASE_URL}/api/content/${slotId}`, { - headers: { - 'If-None-Match': etag - } - }); - - if (result.error) { - console.error('❌ ETag test failed:', result.error); - return false; - } - - if (result.status === 304) { - console.log('✅ ETag caching works (304 Not Modified)'); - return true; - } else { - console.log('⚠️ ETag caching unexpected response:', result.status); - return false; - } -} - -/** - * Test error scenarios - */ -async function testErrorScenarios() { - console.log('\n🚨 Testing error scenarios...'); - - const errorTypes = ['server-error', 'not-found', 'rate-limit', 'unauthorized']; - let passed = 0; - - for (const errorType of errorTypes) { - const result = await makeRequest(`${API_BASE_URL}/api/error/${errorType}`); - - if (result.error) { - console.log(`❌ ${errorType}: ${result.error}`); - } else { - console.log(`✅ ${errorType}: ${result.status}`); - passed++; - } - } - - console.log(` Passed: ${passed}/${errorTypes.length}`); - return passed === errorTypes.length; -} - -/** - * Test metrics endpoint - */ -async function testMetrics() { - console.log('\n📊 Testing metrics endpoint...'); - - const result = await makeRequest(`${API_BASE_URL}/api/metrics`); - - if (result.error) { - console.error('❌ Metrics test failed:', result.error); - return false; - } - - console.log('✅ Metrics endpoint works'); - console.log(' Content store size:', result.data.contentStore.size); - console.log(' ETag store size:', result.data.etagStore.size); - console.log(' Uptime:', Math.round(result.data.uptime), 'seconds'); - - return true; -} - -/** - * Test content update - */ -async function testContentUpdate() { - console.log('\n✏️ Testing content update...'); - - const slotId = 'slot-08:00'; - const newContent = { - content: { - title: 'Updated Test Title', - body: 'This is updated test content', - timestamp: Date.now() - } - }; - - const result = await makeRequest(`${API_BASE_URL}/api/content/${slotId}`, { - method: 'PUT', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(newContent) - }); - - if (result.error) { - console.error('❌ Content update failed:', result.error); - return false; - } - - console.log('✅ Content update works'); - console.log(' Status:', result.status); - console.log(' New ETag:', result.data.etag); - - return true; -} - -/** - * Test content clearing - */ -async function testContentClearing() { - console.log('\n🗑️ Testing content clearing...'); - - const result = await makeRequest(`${API_BASE_URL}/api/content`, { - method: 'DELETE' - }); - - if (result.error) { - console.error('❌ Content clearing failed:', result.error); - return false; - } - - console.log('✅ Content clearing works'); - console.log(' Status:', result.status); - - return true; -} - -/** - * Main test runner - */ -async function runTests() { - console.log('🚀 Starting Test API validation...\n'); - - const tests = [ - { name: 'Health Check', fn: testHealth }, - { name: 'Content Fetching', fn: testContentFetching }, - { name: 'ETag Caching', fn: testETagCaching }, - { name: 'Error Scenarios', fn: testErrorScenarios }, - { name: 'Metrics', fn: testMetrics }, - { name: 'Content Update', fn: testContentUpdate }, - { name: 'Content Clearing', fn: testContentClearing } - ]; - - let passed = 0; - let etag = null; - - for (const test of tests) { - try { - if (test.name === 'ETag Caching' && etag) { - const result = await test.fn(etag); - if (result) passed++; - } else { - const result = await test.fn(); - if (result) { - passed++; - if (test.name === 'Content Fetching' && typeof result === 'string') { - etag = result; - } - } - } - } catch (error) { - console.error(`❌ ${test.name} failed with error:`, error.message); - } - } - - console.log(`\n📋 Test Results: ${passed}/${tests.length} passed`); - - if (passed === tests.length) { - console.log('🎉 All tests passed! Test API is working correctly.'); - } else { - console.log('⚠️ Some tests failed. Check the output above for details.'); - } - - console.log('\n💡 Next steps:'); - console.log(' 1. Start your test app'); - console.log(' 2. Configure it to use this API'); - console.log(' 3. Test plugin functionality'); - console.log(' 4. Monitor API metrics at /api/metrics'); -} - -// Check if API server is running -async function checkServer() { - try { - const result = await makeRequest(`${API_BASE_URL}/health`); - if (result.error) { - console.error('❌ Cannot connect to Test API Server'); - console.error(' Make sure the server is running: npm start'); - console.error(' Server should be available at:', API_BASE_URL); - process.exit(1); - } - } catch (error) { - console.error('❌ Cannot connect to Test API Server'); - console.error(' Make sure the server is running: npm start'); - console.error(' Server should be available at:', API_BASE_URL); - process.exit(1); - } -} - -// Run tests -checkServer().then(() => { - runTests().catch(error => { - console.error('❌ Test runner failed:', error.message); - process.exit(1); - }); -}); diff --git a/test-apps/verify-emulator-network.sh b/test-apps/verify-emulator-network.sh deleted file mode 100755 index e2751fd..0000000 --- a/test-apps/verify-emulator-network.sh +++ /dev/null @@ -1,107 +0,0 @@ -#!/bin/bash - -# Android Emulator Network Verification Script -# Diagnoses network connectivity issues that cause ANRs and Play Services failures -# Author: Matthew Raymer - -echo "🔍 Android Emulator Network Verification" -echo "========================================" -echo "" - -# Check if emulator is running -if ! adb devices | grep -q "emulator.*device"; then - echo "❌ Error: No emulator detected!" - echo "Please start an emulator first" - exit 1 -fi - -echo "✅ Emulator detected" -echo "" - -echo "📋 Network Diagnostics:" -echo "" - -echo "1. 🔧 ADB Connection Status:" -adb devices -echo "" - -echo "2. ✈️ Airplane Mode Status:" -AIRPLANE_MODE=$(adb -e shell settings get global airplane_mode_on 2>/dev/null) -if [ "$AIRPLANE_MODE" = "1" ]; then - echo " ❌ Airplane mode is ON - this will block network access" - echo " 💡 Fix: adb -e shell settings put global airplane_mode_on 0" -else - echo " ✅ Airplane mode is OFF" -fi -echo "" - -echo "3. 🌐 Network Interfaces:" -echo " Network interfaces:" -adb -e shell ip addr | grep -E "(inet |UP|DOWN)" | head -10 -echo "" -echo " Routing table:" -adb -e shell ip route | head -5 -echo "" - -echo "4. 🏓 DNS Resolution Tests:" -echo " Testing Google DNS (8.8.8.8):" -if adb -e shell ping -c1 8.8.8.8 >/dev/null 2>&1; then - echo " ✅ Google DNS reachable" -else - echo " ❌ Google DNS unreachable - host/VPN/firewall blocking" -fi - -echo " Testing connectivity check (connectivitycheck.gstatic.com):" -if adb -e shell ping -c1 connectivitycheck.gstatic.com >/dev/null 2>&1; then - echo " ✅ Hostname resolution working" -else - echo " ❌ Hostname resolution failed - DNS issue" -fi -echo "" - -echo "5. 🔍 Play Services Status:" -echo " Google Play Services:" -adb -e shell dumpsys package com.google.android.gms | grep -E "(versionName|enabled)" | head -2 -echo "" - -echo "6. 📊 Network Monitor Logs:" -echo " Recent network errors (last 10 lines):" -adb -e logcat -d | grep -E "(NetworkMonitor|ECONNREFUSED|UnknownHostException)" | tail -5 -echo "" - -echo "🎯 Diagnosis Summary:" -echo "" - -# Determine issue type -if [ "$AIRPLANE_MODE" = "1" ]; then - echo "❌ PRIMARY ISSUE: Airplane mode is ON" - echo " Solution: Turn off airplane mode" -elif ! adb -e shell ping -c1 8.8.8.8 >/dev/null 2>&1; then - echo "❌ PRIMARY ISSUE: No internet connectivity" - echo " Solutions:" - echo " - Check host VPN/killswitch settings" - echo " - Verify firewall rules allow emulator traffic" - echo " - Try: ./launch-emulator-network-fix.sh" -elif ! adb -e shell ping -c1 connectivitycheck.gstatic.com >/dev/null 2>&1; then - echo "❌ PRIMARY ISSUE: DNS resolution failure" - echo " Solutions:" - echo " - Use explicit DNS: -dns-server 8.8.8.8,1.1.1.1" - echo " - Check corporate proxy settings" - echo " - Try: ./launch-emulator-network-fix.sh" -else - echo "✅ Network connectivity appears normal" - echo " If still experiencing ANRs, check Play Services cache:" - echo " adb -e shell pm clear com.google.android.gms" -fi - -echo "" -echo "🔧 Quick Fixes:" -echo " # Clear Play Services cache" -echo " adb -e shell pm clear com.google.android.gms" -echo " adb -e shell pm clear com.android.vending" -echo "" -echo " # Restart ADB" -echo " adb kill-server && adb start-server" -echo "" -echo " # Launch with network fixes" -echo " ./launch-emulator-network-fix.sh"