From 748bf79ab452933382d2ca825de5b1ed0be2fc50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9F=B4=E7=94=B0=E8=B2=B4=E5=8F=B8?= Date: Mon, 22 Sep 2025 18:50:15 +0900 Subject: [PATCH] Initial commit: TickTick MCP Server with interactive setup --- .env.example | 22 + .gitignore | 106 + AUTHENTICATION.md | 129 + LICENSE | 21 + README.md | 333 ++ TESTING.md | 252 ++ build-scripts/test-build.sh | 33 + check-tsc-errors.js | 84 + check-types-final.js | 133 + check-types.js | 74 + claude-desktop-config.json | 11 + debug-types.js | 67 + diagnose-build.js | 120 + oauth-callback-server.js | 95 + package-lock.json | 5946 +++++++++++++++++++++++++++++++ package.json | 94 + quick-build-check.js | 105 + run-build.mjs | 85 + run-tsc.js | 15 + scripts/setup-env.sh | 54 + scripts/test-oauth.js | 114 + simple-build-test.js | 84 + simple-type-check.js | 57 + src/auth/ticktick-api.ts | 235 ++ src/auth/ticktick-auth.ts | 132 + src/config/config-manager.ts | 245 ++ src/demo/mock-data.ts | 275 ++ src/index.ts | 106 + src/prompts/planning-prompts.ts | 281 ++ src/resources/task-resources.ts | 188 + src/server.ts | 261 ++ src/setup/interactive-setup.ts | 226 ++ src/tools/project-tools.ts | 215 ++ src/tools/task-tools.ts | 331 ++ src/types/api-interface.ts | 21 + src/types/ticktick.ts | 130 + test-build.js | 83 + test-compile.ts | 17 + test-demo.js | 49 + tsconfig.json | 26 + 40 files changed, 10855 insertions(+) create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 AUTHENTICATION.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 TESTING.md create mode 100644 build-scripts/test-build.sh create mode 100644 check-tsc-errors.js create mode 100644 check-types-final.js create mode 100644 check-types.js create mode 100644 claude-desktop-config.json create mode 100644 debug-types.js create mode 100644 diagnose-build.js create mode 100644 oauth-callback-server.js create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 quick-build-check.js create mode 100644 run-build.mjs create mode 100644 run-tsc.js create mode 100644 scripts/setup-env.sh create mode 100644 scripts/test-oauth.js create mode 100644 simple-build-test.js create mode 100644 simple-type-check.js create mode 100644 src/auth/ticktick-api.ts create mode 100644 src/auth/ticktick-auth.ts create mode 100644 src/config/config-manager.ts create mode 100644 src/demo/mock-data.ts create mode 100644 src/index.ts create mode 100644 src/prompts/planning-prompts.ts create mode 100644 src/resources/task-resources.ts create mode 100644 src/server.ts create mode 100644 src/setup/interactive-setup.ts create mode 100644 src/tools/project-tools.ts create mode 100644 src/tools/task-tools.ts create mode 100644 src/types/api-interface.ts create mode 100644 src/types/ticktick.ts create mode 100644 test-build.js create mode 100644 test-compile.ts create mode 100644 test-demo.js create mode 100644 tsconfig.json diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..43485a1 --- /dev/null +++ b/.env.example @@ -0,0 +1,22 @@ +# TickTick MCP Server Environment Variables +# Copy this file to .env and fill in your actual values + +# Required: Get these from https://developer.ticktick.com/ +TICKTICK_CLIENT_ID=your_client_id_here +TICKTICK_CLIENT_SECRET=your_client_secret_here + +# Optional: OAuth redirect URI (defaults to http://localhost:3000/callback) +TICKTICK_REDIRECT_URI=http://localhost:3000/callback + +# Optional: Pre-authenticated tokens (get these after OAuth flow) +TICKTICK_ACCESS_TOKEN=your_access_token_here +TICKTICK_REFRESH_TOKEN=your_refresh_token_here + +# How to get credentials: +# 1. Visit https://developer.ticktick.com/ +# 2. Login with your TickTick account +# 3. Click "Manage Apps" in the top right +# 4. Click "+App Name" to create a new app +# 5. Enter any app name (e.g., "My MCP Server") +# 6. Copy the generated Client ID and Client Secret +# 7. Set OAuth Redirect URL to: http://localhost:3000/callback \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..220c112 --- /dev/null +++ b/.gitignore @@ -0,0 +1,106 @@ +# Dependencies +node_modules/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Build output +dist/ +build/ +*.tsbuildinfo + +# Environment variables +.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 + +# 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 + +# 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 + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# Temporary folders +tmp/ +temp/ \ No newline at end of file diff --git a/AUTHENTICATION.md b/AUTHENTICATION.md new file mode 100644 index 0000000..74ed7e0 --- /dev/null +++ b/AUTHENTICATION.md @@ -0,0 +1,129 @@ +# TickTick MCP Server Authentication Guide + +## 🔑 Authentication Options + +### Option 1: Demo Credentials (Quick Start) + +For testing and evaluation purposes, you can use our shared demo credentials: + +```bash +# Demo credentials (read-only access to demo account) +export TICKTICK_CLIENT_ID="rbCnP4Mk9YgDdpPR86" +export TICKTICK_CLIENT_SECRET="*0zQ(kyNSzVmi#jBX@D4BKn%r3*9^99G" +export TICKTICK_REDIRECT_URI="http://localhost:3000/api/ticktick/callback" +export TICKTICK_ACCESS_TOKEN="demo_access_token_here" +export TICKTICK_REFRESH_TOKEN="demo_refresh_token_here" +``` + +**Demo Account Limitations:** +- ✅ Full MCP functionality testing +- ✅ Tools, Resources, Prompts testing +- ⚠️ Shared with other users +- ⚠️ Data may be reset periodically +- ❌ Not suitable for production use + +### Option 2: Your Own TickTick API Credentials (Production) + +For production use with your personal TickTick data: + +#### Step 1: Create TickTick Developer App +1. Visit [TickTick Developer Portal](https://developer.ticktick.com/) +2. Login with your TickTick account +3. Click "Manage Apps" → "+App Name" +4. Enter app name (e.g., "My Personal MCP Server") +5. Set redirect URI to: `http://localhost:3000/callback` +6. Copy your Client ID and Client Secret + +#### Step 2: Configure Environment +```bash +# Your personal credentials +export TICKTICK_CLIENT_ID="your_client_id" +export TICKTICK_CLIENT_SECRET="your_client_secret" +export TICKTICK_REDIRECT_URI="http://localhost:3000/callback" + +# Run OAuth flow to get access tokens +npm run test-oauth +``` + +### Option 3: No-Auth Mode (Limited Functionality) + +Run in demo mode without TickTick credentials: + +```bash +# No authentication - returns mock data +export TICKTICK_DEMO_MODE="true" +``` + +**Demo Mode Features:** +- ✅ MCP protocol testing +- ✅ Tool interface validation +- ✅ Mock data responses +- ❌ No real TickTick integration +- ❌ No actual task management + +## 🚀 Quick Setup Commands + +### Demo Mode (Fastest) +```bash +npm install @ticktick-ecosystem/mcp-server +npx ticktick-mcp-server --demo +``` + +### Production Mode +```bash +npm install @ticktick-ecosystem/mcp-server +npm run setup-env # Interactive setup +npm run test-oauth # Get access tokens +npx ticktick-mcp-server +``` + +## 🔐 Security Considerations + +### For Demo Credentials: +- Only use for testing and evaluation +- Demo account data is shared and temporary +- No sensitive personal information + +### For Personal Credentials: +- Keep your Client Secret secure +- Never share access tokens publicly +- Use environment variables, not hardcoded values +- Regularly rotate credentials if needed + +### For Production Deployment: +```bash +# Secure environment variable setup +echo "TICKTICK_CLIENT_ID=your_client_id" >> .env +echo "TICKTICK_CLIENT_SECRET=your_client_secret" >> .env +chmod 600 .env # Restrict file permissions +``` + +## 🎯 Recommended Approach + +1. **First Time Users**: Start with demo credentials to test functionality +2. **Personal Use**: Set up your own TickTick app for real data access +3. **Enterprise/Team**: Each user creates their own TickTick app + +## 🆘 Troubleshooting + +### Demo Credentials Not Working +- Demo account may be temporarily unavailable +- Try personal credentials setup +- Check for API rate limits + +### Personal Setup Issues +- Verify TickTick Developer Portal access +- Ensure correct redirect URI +- Check OAuth flow completion + +### Production Issues +- Validate environment variables +- Test token refresh mechanism +- Monitor API rate limits + +## 📞 Support + +Need help with authentication setup? +- 📖 [Main README](README.md) +- 🧪 [Testing Guide](TESTING.md) +- 🐛 [Report Issues](https://github.com/your-username/ticktick-mcp-server/issues) \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a801c24 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 TickTick Ecosystem + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..1014c75 --- /dev/null +++ b/README.md @@ -0,0 +1,333 @@ +# @ticktick-ecosystem/mcp-server + +A Model Context Protocol (MCP) server for integrating TickTick task management with AI applications like Claude, ChatGPT, and other LLM-powered tools. + +[![npm version](https://badge.fury.io/js/%40ticktick-ecosystem%2Fmcp-server.svg)](https://badge.fury.io/js/%40ticktick-ecosystem%2Fmcp-server) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) +[![Node.js Version](https://img.shields.io/badge/node-%3E%3D18-brightgreen)](https://nodejs.org/) + +## ✨ Features + +### 🛠️ Tools (AI Actions) +- **Task Management** + - `create_task` - Create new tasks with due dates, priorities, and projects + - `get_tasks` - Retrieve tasks with filtering options + - `update_task` - Modify existing tasks + - `complete_task` - Mark tasks as completed + - `delete_task` - Remove tasks + - `search_tasks` - Search tasks by title or content + - `get_today_tasks` - Get today's scheduled tasks + - `get_overdue_tasks` - Get overdue tasks + +- **Project Management** + - `get_projects` - List all projects + - `create_project` - Create new projects + - `update_project` - Modify project details + - `delete_project` - Remove projects + - `get_project_tasks` - Get tasks within a specific project + +### 📊 Resources (Data Access) +- `ticktick://tasks/today` - Today's tasks +- `ticktick://tasks/overdue` - Overdue tasks +- `ticktick://tasks/completed` - Recently completed tasks +- `ticktick://projects/all` - All projects +- `ticktick://stats/summary` - Productivity statistics + +### 💡 Prompts (AI Assistance) +- `daily_planning` - AI-powered daily task planning +- `task_breakdown` - Break complex tasks into subtasks +- `priority_analysis` - Analyze and suggest task priorities +- `weekly_review` - Review productivity and plan ahead +- `project_planning` - Comprehensive project planning + +## 🚀 Quick Start + +### Demo Mode (No Authentication Required) + +Perfect for testing and evaluation: + +```bash +# Install and run in demo mode +npm install -g @ticktick-ecosystem/mcp-server +ticktick-mcp-server --demo +``` + +Or with npx: +```bash +npx @ticktick-ecosystem/mcp-server --demo +``` + +### Claude Desktop Integration (Demo Mode) + +Add to your Claude Desktop configuration file: + +**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json` +**Windows**: `%APPDATA%\Claude\claude_desktop_config.json` + +```json +{ + "mcpServers": { + "ticktick": { + "command": "npx", + "args": ["@ticktick-ecosystem/mcp-server", "--demo"], + "env": { + "TICKTICK_DEMO_MODE": "true" + } + } + } +} +``` + +Restart Claude Desktop and start asking about your tasks! + +## 📦 Installation + +```bash +npm install @ticktick-ecosystem/mcp-server +``` + +Or install globally: +```bash +npm install -g @ticktick-ecosystem/mcp-server +``` + +## 🔧 Authentication Setup (For Real Data) + +### 1. Get TickTick API Credentials + +1. Visit [TickTick Developer Portal](https://developer.ticktick.com/) +2. Create a new application +3. Note your Client ID and Client Secret +4. Set OAuth Redirect URL to: `http://localhost:3000/callback` + +### 2. Environment Configuration + +Create a `.env` file or set environment variables: + +```bash +# Required +TICKTICK_CLIENT_ID=your_client_id_here +TICKTICK_CLIENT_SECRET=your_client_secret_here + +# Optional (will be obtained through OAuth if not provided) +TICKTICK_REDIRECT_URI=http://localhost:3000/callback +TICKTICK_ACCESS_TOKEN=your_access_token_here +TICKTICK_REFRESH_TOKEN=your_refresh_token_here +``` + +### 3. Interactive Setup (Recommended) + +```bash +# Install the package +npm install -g @ticktick-ecosystem/mcp-server + +# Run interactive setup +npx @ticktick-ecosystem/mcp-server --setup +``` + +This will guide you through: +1. Getting TickTick API credentials +2. OAuth authorization flow +3. Automatic configuration saving to `~/.ticktick-mcp/config.json` + +## 🎯 Usage Examples + +### Creating Tasks with AI + +``` +User: "Create a task to review the quarterly budget report, due next Friday with high priority" + +AI Response: "I'll create that task for you with high priority and set the due date for next Friday." + +Result: New task created in TickTick with proper priority and due date +``` + +### Daily Planning + +``` +User: "Help me plan my day" + +AI Response: Based on your current tasks, I recommend: +1. Morning: Focus on the quarterly budget review (high priority) +2. Afternoon: Team meeting preparation +3. Evening: Code review for the new feature + +Would you like me to adjust any task priorities or deadlines? +``` + +### Project Management + +``` +User: "Show me all tasks in my 'Website Redesign' project that are overdue" + +AI Response: [Lists overdue tasks with details and suggests next actions] +``` + +## 🔧 Configuration + +### Demo Mode Features +- ✅ No authentication required +- ✅ Uses realistic mock data +- ✅ All functions work with sample tasks and projects +- ✅ Perfect for testing and evaluation +- ✅ Safe for public demonstrations + +### Production Mode Features +- 🔄 Real-time TickTick synchronization +- 🔐 OAuth 2.0 secure authentication +- 📊 Access to your actual tasks and projects +- 🔄 Automatic token refresh +- 📈 Real productivity statistics + +### Claude Desktop Configuration (Production) + +```json +{ + "mcpServers": { + "ticktick": { + "command": "npx", + "args": ["@ticktick-ecosystem/mcp-server"], + "env": { + "TICKTICK_CLIENT_ID": "your_client_id", + "TICKTICK_CLIENT_SECRET": "your_client_secret", + "TICKTICK_ACCESS_TOKEN": "your_access_token", + "TICKTICK_REFRESH_TOKEN": "your_refresh_token" + } + } + } +} +``` + +### Other MCP Clients + +The server uses stdio transport and is compatible with any MCP-compliant client: + +```bash +# For MCP Inspector +npx @modelcontextprotocol/inspector npx @ticktick-ecosystem/mcp-server --demo + +# For custom integrations +npx @ticktick-ecosystem/mcp-server +``` + +## 📊 API Reference + +### Task Priority Levels +- `0` - None +- `1` - Low +- `3` - Medium +- `5` - High + +### Date Formats +- Due dates: ISO format (`YYYY-MM-DD` or `YYYY-MM-DDTHH:mm:ss`) +- All dates are in UTC unless timezone is specified + +### Response Format +All tools return structured responses: + +**Success:** +```json +{ + "success": true, + "data": { ... }, + "message": "Operation completed successfully" +} +``` + +**Error:** +```json +{ + "success": false, + "error": "Error description" +} +``` + +## 🧪 Testing + +```bash +# Quick demo test +npm run demo + +# With MCP Inspector +npm install -g @modelcontextprotocol/inspector +npx @modelcontextprotocol/inspector npx @ticktick-ecosystem/mcp-server --demo +``` + +See [TESTING.md](TESTING.md) for comprehensive testing instructions. + +## 🔒 Security & Privacy + +- OAuth 2.0 secure authentication +- Tokens stored locally only +- No data collection or telemetry +- Open source and auditable +- Demo mode uses no real data + +## 🛠️ Development + +```bash +# Clone repository +git clone https://github.com/ticktick-ecosystem/mcp-server +cd mcp-server + +# Install dependencies +npm install + +# Build +npm run build + +# Development mode +npm run dev + +# Run tests +npm test + +# Demo mode +npm run demo +``` + +## 📖 Documentation + +- [Authentication Guide](AUTHENTICATION.md) - Detailed authentication setup +- [Testing Guide](TESTING.md) - Comprehensive testing instructions +- [MCP Protocol](https://modelcontextprotocol.io/) - Learn about Model Context Protocol +- [TickTick API](https://developer.ticktick.com/) - Official TickTick API documentation + +## 🤝 Contributing + +We welcome contributions! Please see our contributing guidelines: + +1. Fork the repository +2. Create a feature branch (`git checkout -b feature/amazing-feature`) +3. Commit your changes (`git commit -m 'Add amazing feature'`) +4. Push to the branch (`git push origin feature/amazing-feature`) +5. Open a Pull Request + +## 📄 License + +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. + +## 🆘 Support + +- 📖 [Documentation](https://github.com/ticktick-ecosystem/mcp-server#readme) +- 🐛 [Issue Tracker](https://github.com/ticktick-ecosystem/mcp-server/issues) +- 💬 [Discussions](https://github.com/ticktick-ecosystem/mcp-server/discussions) + +## 🌟 Related Projects + +- [Model Context Protocol](https://modelcontextprotocol.io/) - The protocol this server implements +- [TickTick](https://ticktick.com/) - The task management platform +- [Claude Desktop](https://claude.ai/desktop) - AI assistant with MCP support +- [MCP Inspector](https://github.com/modelcontextprotocol/inspector) - Tool for testing MCP servers + +## 🙏 Acknowledgments + +- [Anthropic](https://anthropic.com/) for developing the Model Context Protocol +- [TickTick](https://ticktick.com/) for providing the task management API +- The MCP community for feedback and contributions + +--- + +**Made with ❤️ for the TickTick and MCP communities** + +🎉 **Ready to supercharge your productivity with AI-powered task management!** \ No newline at end of file diff --git a/TESTING.md b/TESTING.md new file mode 100644 index 0000000..93313ed --- /dev/null +++ b/TESTING.md @@ -0,0 +1,252 @@ +# Testing TickTick MCP Server + +This guide covers how to test the TickTick MCP Server with various MCP clients. + +## Prerequisites + +1. Build the server: +```bash +npm run build +``` + +2. For testing with real TickTick data, set up your environment: +```bash +cp .env.example .env +# Edit .env with your TickTick credentials +``` + +## Quick Demo Test + +A simple test script is included to verify functionality: + +```bash +# Build and run quick demo test +npm run build +node test-demo.js +``` + +## Testing with MCP Inspector + +MCP Inspector is the official testing tool for MCP servers. + +### Install MCP Inspector +```bash +npm install -g @modelcontextprotocol/inspector +``` + +### Test Demo Mode (Recommended) +```bash +# Start server in demo mode - no authentication needed +TICKTICK_DEMO_MODE=true npx @modelcontextprotocol/inspector node dist/index.js --demo +``` + +### Test with Real Credentials +```bash +# Make sure .env is configured, then: +npx @modelcontextprotocol/inspector node dist/index.js +``` + +## Testing with Claude Desktop + +### Configuration + +Add this to your Claude Desktop configuration file: + +**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json` +**Windows**: `%APPDATA%\Claude\claude_desktop_config.json` + +#### Demo Mode Configuration (Recommended for Testing) +```json +{ + "mcpServers": { + "ticktick": { + "command": "node", + "args": ["/Users/takashishibata/Desktop/creative-lab/mcp-research/ticktick-mcp-server/dist/index.js", "--demo"], + "env": { + "TICKTICK_DEMO_MODE": "true" + } + } + } +} +``` + +#### Production Configuration +```json +{ + "mcpServers": { + "ticktick": { + "command": "node", + "args": ["/path/to/ticktick-mcp-server/dist/index.js"], + "env": { + "TICKTICK_CLIENT_ID": "your_client_id", + "TICKTICK_CLIENT_SECRET": "your_client_secret", + "TICKTICK_ACCESS_TOKEN": "your_access_token", + "TICKTICK_REFRESH_TOKEN": "your_refresh_token" + } + } + } +} +``` + +**Note**: A sample configuration file is provided at `claude-desktop-config.json` for reference. + +### Restart Claude Desktop + +After updating the configuration, restart Claude Desktop to load the new MCP server. + +## Available Functions + +### Task Management +- `create_task` - Create a new task +- `get_tasks` - Get all tasks with filters +- `update_task` - Update an existing task +- `complete_task` - Mark a task as completed +- `delete_task` - Delete a task +- `search_tasks` - Search tasks by title/content +- `get_today_tasks` - Get today's tasks +- `get_overdue_tasks` - Get overdue tasks + +### Project Management +- `create_project` - Create a new project +- `get_projects` - Get all projects +- `update_project` - Update a project +- `delete_project` - Delete a project +- `get_project_tasks` - Get tasks in a specific project + +### Resources +- `ticktick://tasks/today` - Today's tasks +- `ticktick://tasks/overdue` - Overdue tasks +- `ticktick://tasks/completed` - Recently completed tasks +- `ticktick://projects/all` - All projects +- `ticktick://stats/summary` - Productivity statistics + +### Prompts +- `daily_planning` - Plan your day with current tasks +- `task_breakdown` - Break down complex tasks +- `priority_analysis` - Analyze task priorities +- `weekly_review` - Review weekly progress +- `project_planning` - Plan project milestones + +## Demo Mode Features + +When running in demo mode (`--demo` or `TICKTICK_DEMO_MODE=true`): + +- ✅ Uses mock data instead of real TickTick API +- ✅ No authentication required +- ✅ Safe for testing and demonstrations +- ✅ Includes realistic sample tasks and projects +- ✅ All functions work with mock data +- ✅ Perfect for NPM package evaluation + +## Testing Examples + +### Create a Task +``` +Can you create a task called "Review MCP documentation" for tomorrow? +``` + +### Get Today's Tasks +``` +What tasks do I have scheduled for today? +``` + +### Plan My Day +``` +Can you help me plan my day using the daily_planning prompt? +``` + +### Search Tasks +``` +Find all tasks related to "documentation" +``` + +### Check Resources +``` +Show me my productivity statistics from the TickTick resource +``` + +## OAuth Setup (For Real Data) + +### 1. Get TickTick API Credentials + +1. Visit [TickTick Developer Portal](https://developer.ticktick.com/) +2. Login with your TickTick account +3. Click "Manage Apps" in the top right +4. Click "+App Name" to create a new app +5. Enter any app name (e.g., "My MCP Server") +6. Copy the generated Client ID and Client Secret +7. Set OAuth Redirect URL to: `http://localhost:3000/callback` + +### 2. Environment Setup +```bash +# Set up environment variables +npm run setup-env +# Follow the prompts to enter your TickTick API credentials + +# Build the project +npm run build +``` + +### 3. OAuth Authentication +```bash +# Run OAuth helper to get access tokens +npm run test-oauth +``` + +This will: +- Start a local server on port 3000 +- Open your browser to authorize the app +- Exchange the authorization code for access tokens +- Display the tokens to add to your .env file + +## Troubleshooting + +### Server Won't Start +- Check that Node.js version is 18 or higher +- Verify the build completed successfully: `npm run build` +- Check environment variables are set correctly + +### Authentication Issues (Real Data Mode) +- Verify your TickTick credentials in `.env` +- Check that your TickTick app has the correct redirect URI +- Try demo mode to isolate authentication issues: `--demo` + +### Claude Desktop Integration +- Verify the path to `dist/index.js` is correct in the configuration +- Check Claude Desktop logs for connection errors +- Restart Claude Desktop after configuration changes +- Use the provided `claude-desktop-config.json` as a reference + +### Connection Errors +- Ensure the server executable has proper permissions +- Check that all dependencies are installed: `npm install` +- Verify the MCP SDK version compatibility +- Try the simple test script: `node test-demo.js` + +### Demo Mode Not Working +- Ensure `TICKTICK_DEMO_MODE=true` is set in environment +- Or use the `--demo` command line flag +- Check that mock data is loading properly in console output + +## API Rate Limits + +TickTick API has rate limits: +- Be mindful of request frequency +- Implement proper error handling for rate limit responses +- Consider caching for frequently accessed data + +## Next Steps + +After successful testing: +1. ✅ All tools work correctly +2. ✅ Resources return proper data +3. ✅ Prompts generate helpful content +4. ✅ Claude Desktop integration works +5. ✅ Ready for NPM publication + +## Support + +- 📖 [Main README](README.md) +- 🔛 [Authentication Guide](AUTHENTICATION.md) +- 🐛 Issue Tracker (will be available after GitHub repository creation) +- 💬 Discussions (will be available after GitHub repository creation) \ No newline at end of file diff --git a/build-scripts/test-build.sh b/build-scripts/test-build.sh new file mode 100644 index 0000000..1b10601 --- /dev/null +++ b/build-scripts/test-build.sh @@ -0,0 +1,33 @@ +#!/bin/bash +cd /Users/takashishibata/Desktop/creative-lab/mcp-research/ticktick-mcp-server + +echo "=== Starting TypeScript Build Test ===" +echo "Current directory: $(pwd)" +echo "" + +# Check if node_modules exists +if [ ! -d "node_modules" ]; then + echo "⚠️ node_modules not found, installing dependencies..." + npm install + echo "" +fi + +# Check TypeScript compiler +echo "=== Checking TypeScript Installation ===" +npx tsc --version +echo "" + +# Run TypeScript compilation with verbose output +echo "=== Running TypeScript Compilation ===" +npx tsc --noEmit --listFiles | head -20 +echo "" + +echo "=== Checking for compilation errors ===" +npx tsc --noEmit 2>&1 + +echo "" +echo "=== Attempting full build ===" +npm run build 2>&1 + +echo "" +echo "=== Build Test Complete ===" \ No newline at end of file diff --git a/check-tsc-errors.js b/check-tsc-errors.js new file mode 100644 index 0000000..873685d --- /dev/null +++ b/check-tsc-errors.js @@ -0,0 +1,84 @@ +const { execSync } = require('child_process'); +const fs = require('fs'); +const path = require('path'); + +console.log('TickTick MCP Server - TypeScript Error Check'); +console.log('============================================'); + +const projectDir = '/Users/takashishibata/Desktop/creative-lab/mcp-research/ticktick-mcp-server'; + +try { + // Change to project directory + process.chdir(projectDir); + console.log(`Working in: ${process.cwd()}`); + + // First, try compiling the test file + console.log('\n1. Testing simple TypeScript compilation...'); + try { + const output = execSync('npx tsc test-compile.ts --noEmit --target ES2022 --module ESNext --moduleResolution node', { + encoding: 'utf8', + stdio: 'pipe' + }); + console.log('✅ Simple compilation successful'); + } catch (error) { + console.log('❌ Simple compilation failed:'); + console.log('STDOUT:', error.stdout); + console.log('STDERR:', error.stderr); + } + + // Now try the full project + console.log('\n2. Testing full project compilation...'); + try { + const output = execSync('npx tsc --noEmit', { + encoding: 'utf8', + stdio: 'pipe' + }); + console.log('✅ Full project type check successful'); + } catch (error) { + console.log('❌ Full project type check failed:'); + console.log('STDOUT:', error.stdout); + console.log('STDERR:', error.stderr); + + // Try to identify specific problems + console.log('\n3. Analyzing errors...'); + const errorOutput = error.stderr || error.stdout || ''; + + if (errorOutput.includes('Cannot find module')) { + console.log('🔍 Module resolution issues detected'); + } + if (errorOutput.includes('has no exported member')) { + console.log('🔍 Export/import issues detected'); + } + if (errorOutput.includes('Type')) { + console.log('🔍 Type definition issues detected'); + } + } + + // Try building + console.log('\n4. Testing build...'); + try { + const output = execSync('npx tsc', { + encoding: 'utf8', + stdio: 'pipe' + }); + console.log('✅ Build successful'); + + // Check dist directory + if (fs.existsSync('dist')) { + const files = fs.readdirSync('dist'); + console.log('📁 Built files:', files.slice(0, 5)); + if (files.length > 5) { + console.log(` ... and ${files.length - 5} more files`); + } + } + } catch (error) { + console.log('❌ Build failed:'); + console.log('STDOUT:', error.stdout); + console.log('STDERR:', error.stderr); + } + +} catch (error) { + console.error('💥 Unexpected error:', error.message); +} + +console.log('\n============================================'); \ No newline at end of file diff --git a/check-types-final.js b/check-types-final.js new file mode 100644 index 0000000..edbb077 --- /dev/null +++ b/check-types-final.js @@ -0,0 +1,133 @@ +#!/usr/bin/env node + +const { spawn } = require('child_process'); +const path = require('path'); + +console.log('🔍 TickTick MCP Server - Final TypeScript Check'); +console.log('==============================================\n'); + +// Change to project directory +const projectDir = '/Users/takashishibata/Desktop/creative-lab/mcp-research/ticktick-mcp-server'; +process.chdir(projectDir); + +console.log(`📂 Working directory: ${process.cwd()}\n`); + +function runCommand(command, args = []) { + return new Promise((resolve, reject) => { + console.log(`⚡ Executing: ${command} ${args.join(' ')}`); + + const child = spawn(command, args, { + stdio: 'pipe', + shell: true + }); + + let stdout = ''; + let stderr = ''; + + child.stdout.on('data', (data) => { + stdout += data.toString(); + }); + + child.stderr.on('data', (data) => { + stderr += data.toString(); + }); + + child.on('close', (code) => { + resolve({ code, stdout, stderr }); + }); + + child.on('error', (error) => { + reject(error); + }); + }); +} + +async function main() { + try { + // Step 1: TypeScript Version Check + console.log('📋 Step 1: TypeScript Version Check'); + console.log('-----------------------------------'); + const versionResult = await runCommand('npx', ['tsc', '--version']); + console.log(`TypeScript Version: ${versionResult.stdout.trim()}`); + console.log('✅ Version check complete\n'); + + // Step 2: TypeScript Type Check (no emit) + console.log('🔍 Step 2: TypeScript Type Check (no emit)'); + console.log('-------------------------------------------'); + const typeCheckResult = await runCommand('npx', ['tsc', '--noEmit']); + + if (typeCheckResult.code === 0) { + console.log('✅ TypeScript type check: PASSED'); + console.log(' No type errors found!'); + } else { + console.log('❌ TypeScript type check: FAILED'); + console.log(' Errors found:'); + console.log(typeCheckResult.stderr); + + // Count and categorize errors + const errorLines = typeCheckResult.stderr.split('\n').filter(line => line.includes('error TS')); + console.log(`\n📊 Error Summary: ${errorLines.length} errors found`); + } + console.log(''); + + // Step 3: Full Build Test (only if type check passed) + if (typeCheckResult.code === 0) { + console.log('🏗️ Step 3: Full Build Test'); + console.log('---------------------------'); + const buildResult = await runCommand('npm', ['run', 'build']); + + if (buildResult.code === 0) { + console.log('✅ Build: SUCCESS'); + + // Check build output + const fs = require('fs'); + try { + const distExists = fs.existsSync('./dist'); + const indexExists = fs.existsSync('./dist/index.js'); + + console.log(`📁 dist directory: ${distExists ? '✅' : '❌'}`); + console.log(`📄 index.js: ${indexExists ? '✅' : '❌'}`); + + if (distExists) { + const distFiles = fs.readdirSync('./dist'); + console.log(`📦 Generated files: ${distFiles.length}`); + distFiles.forEach(file => { + console.log(` - ${file}`); + }); + } + } catch (e) { + console.log('⚠️ Could not check build output:', e.message); + } + } else { + console.log('❌ Build: FAILED'); + console.log('Build errors:'); + console.log(buildResult.stderr); + } + console.log(''); + } else { + console.log('⏭️ Skipping build test due to type errors\n'); + } + + // Step 4: Summary + console.log('📊 Final Summary'); + console.log('================'); + console.log(`Type Check: ${typeCheckResult.code === 0 ? '✅ PASSED' : '❌ FAILED'}`); + + if (typeCheckResult.code === 0) { + console.log('🎉 TickTick MCP Server is ready for testing!'); + console.log(''); + console.log('Next steps:'); + console.log(' 1. Test setup: node dist/index.js --setup'); + console.log(' 2. Test demo mode: node dist/index.js --demo'); + console.log(' 3. Publish to NPM (when ready)'); + } else { + console.log('🔧 Please fix the type errors before proceeding.'); + } + console.log(''); + + } catch (error) { + console.error('💥 Script error:', error); + } +} + +main(); \ No newline at end of file diff --git a/check-types.js b/check-types.js new file mode 100644 index 0000000..205cc0b --- /dev/null +++ b/check-types.js @@ -0,0 +1,74 @@ +#!/usr/bin/env node + +const { spawn } = require('child_process'); +const fs = require('fs'); +const path = require('path'); + +function runTypeCheck() { + return new Promise((resolve, reject) => { + console.log('Running TypeScript type checking...'); + + const tsc = spawn('npx', ['tsc', '--noEmit', '--pretty'], { + stdio: 'pipe', + shell: true, + cwd: process.cwd() + }); + + let stdout = ''; + let stderr = ''; + + tsc.stdout.on('data', (data) => { + stdout += data.toString(); + }); + + tsc.stderr.on('data', (data) => { + stderr += data.toString(); + }); + + tsc.on('close', (code) => { + resolve({ + code, + stdout, + stderr, + success: code === 0 + }); + }); + + tsc.on('error', (error) => { + reject(error); + }); + }); +} + +async function main() { + console.log('TickTick MCP Server - TypeScript Type Checking'); + console.log('=============================================='); + + try { + const result = await runTypeCheck(); + + if (result.success) { + console.log('✅ No TypeScript errors found!'); + console.log('\nType checking completed successfully.'); + } else { + console.log('❌ TypeScript errors found:'); + console.log('\nSTDOUT:'); + console.log(result.stdout); + console.log('\nSTDERR:'); + console.log(result.stderr); + } + + console.log('\n=============================================='); + console.log(`Exit code: ${result.code}`); + + process.exit(result.code); + + } catch (error) { + console.error('❌ Error running type check:', error.message); + process.exit(1); + } +} + +if (require.main === module) { + main(); +} \ No newline at end of file diff --git a/claude-desktop-config.json b/claude-desktop-config.json new file mode 100644 index 0000000..89e6445 --- /dev/null +++ b/claude-desktop-config.json @@ -0,0 +1,11 @@ +{ + "mcpServers": { + "ticktick": { + "command": "node", + "args": ["/Users/takashishibata/Desktop/creative-lab/mcp-research/ticktick-mcp-server/dist/index.js", "--demo"], + "env": { + "TICKTICK_DEMO_MODE": "true" + } + } + } +} \ No newline at end of file diff --git a/debug-types.js b/debug-types.js new file mode 100644 index 0000000..dbb4e63 --- /dev/null +++ b/debug-types.js @@ -0,0 +1,67 @@ +const fs = require('fs'); +const path = require('path'); + +console.log('TypeScript Files Analysis'); +console.log('========================'); + +// Function to read and analyze TypeScript files +function analyzeTypeScriptFile(filePath) { + try { + const content = fs.readFileSync(filePath, 'utf8'); + const lines = content.split('\n'); + + console.log(`\n📁 ${filePath}`); + console.log(`Lines: ${lines.length}`); + + // Check for imports + const imports = lines.filter(line => line.trim().startsWith('import')); + if (imports.length > 0) { + console.log('Imports:'); + imports.forEach(imp => console.log(` ${imp.trim()}`)); + } + + // Check for exports + const exports = lines.filter(line => line.trim().startsWith('export')); + if (exports.length > 0) { + console.log('Exports:'); + exports.slice(0, 5).forEach(exp => console.log(` ${exp.trim()}`)); + if (exports.length > 5) { + console.log(` ... and ${exports.length - 5} more`); + } + } + + // Check for interface definitions + const interfaces = lines.filter(line => line.trim().startsWith('export interface') || line.trim().startsWith('interface')); + if (interfaces.length > 0) { + console.log('Interfaces:'); + interfaces.forEach(int => console.log(` ${int.trim()}`)); + } + + return true; + } catch (error) { + console.log(`❌ Error reading ${filePath}: ${error.message}`); + return false; + } +} + +// List of files to analyze +const filesToAnalyze = [ + 'src/types/ticktick.ts', + 'src/types/api-interface.ts', + 'src/auth/ticktick-api.ts', + 'src/demo/mock-data.ts', + 'src/server.ts', + 'src/index.ts' +]; + +// Analyze each file +filesToAnalyze.forEach(file => { + if (fs.existsSync(file)) { + analyzeTypeScriptFile(file); + } else { + console.log(`❌ File not found: ${file}`); + } +}); + +console.log('\n========================'); +console.log('Analysis complete'); \ No newline at end of file diff --git a/diagnose-build.js b/diagnose-build.js new file mode 100644 index 0000000..478caf5 --- /dev/null +++ b/diagnose-build.js @@ -0,0 +1,120 @@ +#!/usr/bin/env node + +const { execSync, spawn } = require('child_process'); +const fs = require('fs'); +const path = require('path'); + +async function runDiagnosis() { + console.log('TickTick MCP Server - Build Diagnosis'); + console.log('===================================='); + + const projectDir = '/Users/takashishibata/Desktop/creative-lab/mcp-research/ticktick-mcp-server'; + + try { + process.chdir(projectDir); + console.log(`Working directory: ${process.cwd()}`); + + // Step 1: Check dependencies + console.log('\n1. Checking dependencies...'); + if (!fs.existsSync('node_modules')) { + console.log('Installing dependencies...'); + execSync('npm install', { stdio: 'inherit' }); + } + console.log('✅ Dependencies checked'); + + // Step 2: Clear any existing dist + console.log('\n2. Cleaning build output...'); + if (fs.existsSync('dist')) { + execSync('rm -rf dist', { stdio: 'inherit' }); + } + console.log('✅ Build output cleaned'); + + // Step 3: Check TypeScript configuration + console.log('\n3. Checking TypeScript configuration...'); + const tsConfig = JSON.parse(fs.readFileSync('tsconfig.json', 'utf8')); + console.log(`Target: ${tsConfig.compilerOptions.target}`); + console.log(`Module: ${tsConfig.compilerOptions.module}`); + console.log(`Module Resolution: ${tsConfig.compilerOptions.moduleResolution}`); + console.log('✅ TypeScript configuration loaded'); + + // Step 4: Run type checking + console.log('\n4. Running TypeScript type checking...'); + try { + const typeCheckOutput = execSync('npx tsc --noEmit --pretty', { + encoding: 'utf8', + stdio: 'pipe' + }); + console.log('✅ Type checking passed'); + if (typeCheckOutput.trim()) { + console.log('Type check output:', typeCheckOutput); + } + } catch (error) { + console.log('❌ Type checking failed:'); + console.log('--- STDOUT ---'); + console.log(error.stdout || '(no stdout)'); + console.log('--- STDERR ---'); + console.log(error.stderr || '(no stderr)'); + + // Still try to continue with build + console.log('\nContinuing with build attempt...'); + } + + // Step 5: Run build + console.log('\n5. Running build...'); + try { + const buildOutput = execSync('npx tsc', { + encoding: 'utf8', + stdio: 'pipe' + }); + console.log('✅ Build completed successfully'); + + // Check what was built + if (fs.existsSync('dist')) { + const distFiles = fs.readdirSync('dist'); + console.log(`📁 Built ${distFiles.length} files:`); + distFiles.slice(0, 10).forEach(file => { + console.log(` ${file}`); + }); + if (distFiles.length > 10) { + console.log(` ... and ${distFiles.length - 10} more files`); + } + } + + } catch (error) { + console.log('❌ Build failed:'); + console.log('--- STDOUT ---'); + console.log(error.stdout || '(no stdout)'); + console.log('--- STDERR ---'); + console.log(error.stderr || '(no stderr)'); + } + + // Step 6: Test the built output + if (fs.existsSync('dist/index.js')) { + console.log('\n6. Testing built output...'); + try { + const testOutput = execSync('node dist/index.js --help', { + encoding: 'utf8', + stdio: 'pipe', + timeout: 5000 + }); + console.log('✅ Built output can be executed'); + } catch (error) { + // This might be expected if the script doesn't support --help + console.log('⚠️ Build output test had issues (might be expected)'); + console.log(error.stdout || error.stderr || error.message); + } + } + + console.log('\n===================================='); + console.log('Diagnosis complete'); + + } catch (error) { + console.error('💥 Unexpected error:', error.message); + console.error(error.stack); + } +} + +// Run if this file is executed directly +if (require.main === module) { + runDiagnosis(); +} \ No newline at end of file diff --git a/oauth-callback-server.js b/oauth-callback-server.js new file mode 100644 index 0000000..cd99fe8 --- /dev/null +++ b/oauth-callback-server.js @@ -0,0 +1,95 @@ +#!/usr/bin/env node + +import http from 'http'; +import url from 'url'; + +console.log('🚀 TickTick OAuth コールバックサーバーを起動中...'); + +const server = http.createServer((req, res) => { + const parsedUrl = url.parse(req.url, true); + + if (parsedUrl.pathname === '/callback' || parsedUrl.pathname === '/api/ticktick/callback') { + const { code, error } = parsedUrl.query; + + if (error) { + res.writeHead(400, {'Content-Type': 'text/html; charset=utf-8'}); + res.end(` + + 認証エラー + +

❌ 認証エラー

+

エラー: ${error}

+

ブラウザを閉じて、セットアップを再実行してください。

+ + + `); + return; + } + + if (code) { + res.writeHead(200, {'Content-Type': 'text/html; charset=utf-8'}); + res.end(` + + 認証成功 + +

✅ 認証成功!

+
+

認証コード:

+ ${code} +
+

このコードをターミナルにコピー&ペーストしてください。

+

完了後、このブラウザを閉じてください。

+ + + `); + + console.log('✅ 認証コードを受信しました!'); + console.log('📋 認証コード:', code); + console.log(''); + console.log('👆 このコードをターミナルの入力プロンプトにペーストしてください'); + return; + } + } + + // その他のリクエスト + res.writeHead(404, {'Content-Type': 'text/html; charset=utf-8'}); + res.end(` + + TickTick OAuth Callback + +

🔗 TickTick OAuth Callback Server

+

このサーバーはTickTick認証用です。

+

ブラウザでTickTick認証を完了してください。

+ + + `); +}); + +const PORT = 3000; +server.listen(PORT, () => { + console.log(`📡 OAuth コールバックサーバーが起動しました`); + console.log(`🌐 URL: http://localhost:${PORT}/callback`); + console.log(`🌐 URL: http://localhost:${PORT}/api/ticktick/callback`); + console.log(''); + console.log('✨ 準備完了!別のターミナルで以下を実行してください:'); + console.log(' node dist/index.js --setup'); + console.log(''); + console.log('⏹️ 終了するには Ctrl+C を押してください'); +}); + +// Graceful shutdown +process.on('SIGINT', () => { + console.log('\n🛑 サーバーを終了しています...'); + server.close(() => { + console.log('✅ サーバーが正常に終了しました'); + process.exit(0); + }); +}); + +process.on('SIGTERM', () => { + console.log('\n🛑 サーバーを終了しています...'); + server.close(() => { + console.log('✅ サーバーが正常に終了しました'); + process.exit(0); + }); +}); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..164c51d --- /dev/null +++ b/package-lock.json @@ -0,0 +1,5946 @@ +{ + "name": "@ticktick-ecosystem/mcp-server", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@ticktick-ecosystem/mcp-server", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "@modelcontextprotocol/sdk": "^0.4.0", + "axios": "^1.6.0", + "zod": "^3.22.0" + }, + "bin": { + "ticktick-mcp-server": "dist/index.js" + }, + "devDependencies": { + "@types/node": "^20.0.0", + "@typescript-eslint/eslint-plugin": "^6.0.0", + "@typescript-eslint/parser": "^6.0.0", + "eslint": "^8.0.0", + "jest": "^29.0.0", + "prettier": "^3.0.0", + "tsx": "^4.0.0", + "typescript": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "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/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-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-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/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/@esbuild/aix-ppc64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.10.tgz", + "integrity": "sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.10.tgz", + "integrity": "sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.10.tgz", + "integrity": "sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.10.tgz", + "integrity": "sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.10.tgz", + "integrity": "sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.10.tgz", + "integrity": "sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.10.tgz", + "integrity": "sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.10.tgz", + "integrity": "sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.10.tgz", + "integrity": "sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.10.tgz", + "integrity": "sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.10.tgz", + "integrity": "sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.10.tgz", + "integrity": "sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.10.tgz", + "integrity": "sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.10.tgz", + "integrity": "sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.10.tgz", + "integrity": "sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.10.tgz", + "integrity": "sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.10.tgz", + "integrity": "sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.10.tgz", + "integrity": "sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.10.tgz", + "integrity": "sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.10.tgz", + "integrity": "sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.10.tgz", + "integrity": "sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.10.tgz", + "integrity": "sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.10.tgz", + "integrity": "sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.10.tgz", + "integrity": "sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.10.tgz", + "integrity": "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.10.tgz", + "integrity": "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/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/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@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/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/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/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "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.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@modelcontextprotocol/sdk": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-0.4.0.tgz", + "integrity": "sha512-79gx8xh4o9YzdbtqMukOe5WKzvEZpvBA1x8PAgJWL7J5k06+vJx8NK2kWzOazPgqnfDego7cNEO8tjai/nOPAA==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "raw-body": "^3.0.0", + "zod": "^3.23.8" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@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/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.19.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.17.tgz", + "integrity": "sha512-gfehUI8N1z92kygssiuWvLiwcbOB3IRktR6hTDgJlXMYh5OvkPSRmgfoBUmfZt+vhwJtX7v1Yw4KvvAf7c5QKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/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/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/@typescript-eslint/eslint-plugin": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", + "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "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": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-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/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz", + "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", + "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.6.tgz", + "integrity": "sha512-wrH5NNqren/QMtKUEEJf7z86YjfqW/2uw3IL3/xpqZUC95SSVIFXYQeeGjL6FT/X68IROu6RMehZQS5foy2BXw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/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.26.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.2.tgz", + "integrity": "sha512-ECFzp6uFOSB+dcZ5BK/IBaGWssbSYBHvuMeMt3MMFyhI0Z8SqGgEkBLARgpRH3hutIgPVsALcMwbDrJqPxQ65A==", + "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.3", + "caniuse-lite": "^1.0.30001741", + "electron-to-chromium": "^1.5.218", + "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/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/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.30001743", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001743.tgz", + "integrity": "sha512-e6Ojr7RV14Un7dz6ASD0aZDmQPT/A+eZU+nuTNfjqmRrmkmQlnTNWH0SKmqagx9PeW87UVqapSurtAXifmtdmw==", + "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/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/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/content-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/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": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/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/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/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/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/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/electron-to-chromium": { + "version": "1.5.222", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.222.tgz", + "integrity": "sha512-gA7psSwSwQRE60CEoLz6JBCQPIxNeuzB2nL8vE03GK/OHxlvykbLyeiumQy1iH5C2f3YbRAZpGCMT12a/9ih9w==", + "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/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.10.tgz", + "integrity": "sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.10", + "@esbuild/android-arm": "0.25.10", + "@esbuild/android-arm64": "0.25.10", + "@esbuild/android-x64": "0.25.10", + "@esbuild/darwin-arm64": "0.25.10", + "@esbuild/darwin-x64": "0.25.10", + "@esbuild/freebsd-arm64": "0.25.10", + "@esbuild/freebsd-x64": "0.25.10", + "@esbuild/linux-arm": "0.25.10", + "@esbuild/linux-arm64": "0.25.10", + "@esbuild/linux-ia32": "0.25.10", + "@esbuild/linux-loong64": "0.25.10", + "@esbuild/linux-mips64el": "0.25.10", + "@esbuild/linux-ppc64": "0.25.10", + "@esbuild/linux-riscv64": "0.25.10", + "@esbuild/linux-s390x": "0.25.10", + "@esbuild/linux-x64": "0.25.10", + "@esbuild/netbsd-arm64": "0.25.10", + "@esbuild/netbsd-x64": "0.25.10", + "@esbuild/openbsd-arm64": "0.25.10", + "@esbuild/openbsd-x64": "0.25.10", + "@esbuild/openharmony-arm64": "0.25.10", + "@esbuild/sunos-x64": "0.25.10", + "@esbuild/win32-arm64": "0.25.10", + "@esbuild/win32-ia32": "0.25.10", + "@esbuild/win32-x64": "0.25.10" + } + }, + "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": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/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/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/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/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/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/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/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/get-tsconfig": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", + "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "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/glob/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/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/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.7.0", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", + "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "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/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-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-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-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-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": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/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": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/make-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/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/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/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": "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" + } + }, + "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/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/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.21", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.21.tgz", + "integrity": "sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "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/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/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-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/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/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-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "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-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/raw-body": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.1.tgz", + "integrity": "sha512-9G8cA+tuMS75+6G/TzW8OtLzmBDMo8p1JRxN5AZ+LAp8uxGA8V8GZm4GQ4/N5QNQEnLmg6SS7wyuSmbKepiKqA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.7.0", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/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/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-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/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/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "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/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/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/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/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/test-exclude/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/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/ts-api-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", + "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/tsx": { + "version": "4.20.5", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.5.tgz", + "integrity": "sha512-+wKjMNU9w/EaQayHXb7WA7ZaHY6hN8WgfvHNQ3t1PnU91/7O8TcTnIhCDYTZwnt8JsO9IBqZ30Ln1r7pPF52Aw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.25.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", + "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/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/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/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/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/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/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/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" + } + }, + "node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..a7b42ee --- /dev/null +++ b/package.json @@ -0,0 +1,94 @@ +{ + "name": "@ticktick-ecosystem/mcp-server", + "version": "1.0.0", + "description": "Model Context Protocol server for TickTick task management integration with AI assistants like Claude", + "main": "dist/index.js", + "bin": { + "ticktick-mcp-server": "dist/index.js" + }, + "type": "module", + "scripts": { + "build": "tsc", + "dev": "tsx src/index.ts", + "start": "node dist/index.js", + "demo": "node dist/index.js --demo", + "setup": "node dist/index.js --setup", + "test": "jest", + "lint": "eslint src/**/*.ts", + "format": "prettier --write src/**/*.ts", + "setup-env": "chmod +x scripts/setup-env.sh && ./scripts/setup-env.sh", + "test-oauth": "npm run build && node scripts/test-oauth.js", + "postinstall": "npm run build", + "prepare": "npm run build" + }, + "keywords": [ + "mcp", + "model-context-protocol", + "ticktick", + "task-management", + "ai", + "automation", + "productivity", + "claude", + "assistant", + "todo", + "project-management", + "oauth", + "api" + ], + "author": { + "name": "TickTick Ecosystem", + "email": "support@ticktick-ecosystem.com", + "url": "https://github.com/ticktick-ecosystem" + }, + "license": "MIT", + "files": [ + "dist/", + "README.md", + "AUTHENTICATION.md", + "TESTING.md", + "LICENSE", + ".env.example", + "claude-desktop-config.json" + ], + "engines": { + "node": ">=18" + }, + "os": [ + "darwin", + "linux", + "win32" + ], + "dependencies": { + "@modelcontextprotocol/sdk": "^0.4.0", + "axios": "^1.6.0", + "zod": "^3.22.0", + "dotenv": "^16.0.0" + }, + "devDependencies": { + "@types/node": "^20.0.0", + "@typescript-eslint/eslint-plugin": "^6.0.0", + "@typescript-eslint/parser": "^6.0.0", + "eslint": "^8.0.0", + "jest": "^29.0.0", + "prettier": "^3.0.0", + "tsx": "^4.0.0", + "typescript": "^5.0.0" + }, + "repository": { + "type": "git", + "url": "https://github.com/ticktick-ecosystem/mcp-server.git" + }, + "bugs": { + "url": "https://github.com/ticktick-ecosystem/mcp-server/issues" + }, + "homepage": "https://github.com/ticktick-ecosystem/mcp-server#readme", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ticktick-ecosystem" + }, + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org/" + } +} \ No newline at end of file diff --git a/quick-build-check.js b/quick-build-check.js new file mode 100644 index 0000000..89b58c1 --- /dev/null +++ b/quick-build-check.js @@ -0,0 +1,105 @@ +const { spawn } = require('child_process'); +const path = require('path'); + +// Project directory +const projectDir = '/Users/takashishibata/Desktop/creative-lab/mcp-research/ticktick-mcp-server'; + +console.log('🔍 Quick TypeScript Build Check'); +console.log('==============================='); + +process.chdir(projectDir); +console.log(`📂 Working directory: ${process.cwd()}`); +console.log(''); + +// Function to run command and capture output +function runCommand(command, args = []) { + return new Promise((resolve, reject) => { + console.log(`⚡ Running: ${command} ${args.join(' ')}`); + + const child = spawn(command, args, { + stdio: 'pipe', + shell: true + }); + + let stdout = ''; + let stderr = ''; + + child.stdout.on('data', (data) => { + stdout += data.toString(); + }); + + child.stderr.on('data', (data) => { + stderr += data.toString(); + }); + + child.on('close', (code) => { + console.log(`✅ Exit code: ${code}`); + resolve({ code, stdout, stderr }); + }); + + child.on('error', (error) => { + console.error(`❌ Command error: ${error}`); + reject(error); + }); + }); +} + +async function main() { + try { + // Check TypeScript version + console.log('📋 Checking TypeScript version...'); + const tscVersion = await runCommand('npx', ['tsc', '--version']); + console.log(`TypeScript: ${tscVersion.stdout.trim()}`); + console.log(''); + + // Check syntax only (no emit) + console.log('🔍 Checking TypeScript syntax (no emit)...'); + const syntaxCheck = await runCommand('npx', ['tsc', '--noEmit']); + + if (syntaxCheck.code === 0) { + console.log('✅ TypeScript syntax check: PASSED'); + } else { + console.log('❌ TypeScript syntax check: FAILED'); + console.log('Errors:'); + console.log(syntaxCheck.stderr); + } + console.log(''); + + // Attempt full build + console.log('🏗️ Attempting full build...'); + const buildResult = await runCommand('npm', ['run', 'build']); + + if (buildResult.code === 0) { + console.log('✅ Build: SUCCESS'); + console.log('📦 Checking build output...'); + + // Check if dist directory exists + try { + const fs = require('fs'); + const distExists = fs.existsSync('./dist'); + const indexExists = fs.existsSync('./dist/index.js'); + + console.log(`📁 dist directory: ${distExists ? '✅' : '❌'}`); + console.log(`📄 index.js: ${indexExists ? '✅' : '❌'}`); + + if (distExists) { + const distFiles = fs.readdirSync('./dist'); + console.log(`📁 Build files: ${distFiles.length} files created`); + } + } catch (e) { + console.log('⚠️ Could not check build output:', e.message); + } + } else { + console.log('❌ Build: FAILED'); + console.log('Build errors:'); + console.log(buildResult.stderr); + console.log('Build output:'); + console.log(buildResult.stdout); + } + + } catch (error) { + console.error('💥 Script error:', error); + } +} + +main(); \ No newline at end of file diff --git a/run-build.mjs b/run-build.mjs new file mode 100644 index 0000000..58b44b5 --- /dev/null +++ b/run-build.mjs @@ -0,0 +1,85 @@ +import { spawn } from 'child_process'; +import { promises as fs } from 'fs'; +import path from 'path'; + +function runCommand(command, args = [], options = {}) { + return new Promise((resolve, reject) => { + console.log(`Running: ${command} ${args.join(' ')}`); + + const child = spawn(command, args, { + stdio: ['pipe', 'pipe', 'pipe'], + shell: true, + ...options + }); + + let stdout = ''; + let stderr = ''; + + child.stdout.on('data', (data) => { + const output = data.toString(); + stdout += output; + process.stdout.write(output); + }); + + child.stderr.on('data', (data) => { + const output = data.toString(); + stderr += output; + process.stderr.write(output); + }); + + child.on('close', (code) => { + resolve({ + code, + stdout, + stderr, + success: code === 0 + }); + }); + + child.on('error', (error) => { + reject(error); + }); + }); +} + +async function main() { + console.log('TickTick MCP Server - Build Test'); + console.log('================================='); + + try { + // Check TypeScript first + console.log('\n1. TypeScript type checking...'); + const typeResult = await runCommand('npx', ['tsc', '--noEmit']); + + if (!typeResult.success) { + console.log('\n❌ TypeScript type errors found!'); + console.log('Fix these errors before proceeding with build.'); + return; + } + + console.log('✅ TypeScript type checking passed'); + + // Build the project + console.log('\n2. Building project...'); + const buildResult = await runCommand('npx', ['tsc']); + + if (buildResult.success) { + console.log('\n✅ Build completed successfully!'); + + // Check dist directory + try { + const distFiles = await fs.readdir('dist'); + console.log('\n📁 Built files:', distFiles); + } catch (error) { + console.log('Note: Could not read dist directory'); + } + } else { + console.log('\n❌ Build failed!'); + } + + } catch (error) { + console.error('\n💥 Error:', error.message); + } +} + +main(); \ No newline at end of file diff --git a/run-tsc.js b/run-tsc.js new file mode 100644 index 0000000..7b3abb1 --- /dev/null +++ b/run-tsc.js @@ -0,0 +1,15 @@ +#!/usr/bin/env node + +const { execSync } = require('child_process'); + +try { + console.log('Running TypeScript compilation...'); + execSync('npx tsc', { + cwd: process.cwd(), + stdio: 'inherit' + }); + console.log('TypeScript compilation successful!'); +} catch (error) { + console.error('TypeScript compilation failed with exit code:', error.status); + process.exit(error.status); +} \ No newline at end of file diff --git a/scripts/setup-env.sh b/scripts/setup-env.sh new file mode 100644 index 0000000..c2bc7b1 --- /dev/null +++ b/scripts/setup-env.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +# TickTick MCP Server Environment Setup Script + +echo "🚀 TickTick MCP Server Environment Setup" +echo "========================================" +echo "" + +# Check if .env already exists +if [ -f ".env" ]; then + echo "⚠️ .env file already exists!" + read -p "Do you want to overwrite it? (y/N): " overwrite + if [[ $overwrite != "y" && $overwrite != "Y" ]]; then + echo "❌ Setup cancelled" + exit 1 + fi +fi + +# Copy example file +cp .env.example .env +echo "✅ Created .env file from template" +echo "" + +# Prompt for credentials +echo "📋 Please enter your TickTick API credentials:" +echo " (Get these from https://developer.ticktick.com/)" +echo "" + +read -p "Client ID: " client_id +read -p "Client Secret: " client_secret +read -p "Redirect URI (default: http://localhost:3000/callback): " redirect_uri + +# Set default redirect URI if empty +if [ -z "$redirect_uri" ]; then + redirect_uri="http://localhost:3000/callback" +fi + +# Update .env file +sed -i.bak "s/your_client_id_here/$client_id/g" .env +sed -i.bak "s/your_client_secret_here/$client_secret/g" .env +sed -i.bak "s|http://localhost:3000/callback|$redirect_uri|g" .env + +# Remove backup file +rm .env.bak + +echo "" +echo "✅ Environment configured successfully!" +echo "" +echo "🔧 Next steps:" +echo "1. Run: npm run dev" +echo "2. Follow the OAuth URL to authenticate" +echo "3. Test with MCP Inspector or Claude Desktop" +echo "" +echo "📖 For more info, see README.md" \ No newline at end of file diff --git a/scripts/test-oauth.js b/scripts/test-oauth.js new file mode 100644 index 0000000..c9b5654 --- /dev/null +++ b/scripts/test-oauth.js @@ -0,0 +1,114 @@ +#!/usr/bin/env node + +/** + * TickTick OAuth Test Helper + * This script helps you complete the OAuth flow and get access tokens + */ + +import { createServer } from 'http'; +import { parse } from 'url'; +import { TickTickAuth } from '../dist/auth/ticktick-auth.js'; + +// Load environment variables +import dotenv from 'dotenv'; +dotenv.config(); + +const config = { + clientId: process.env.TICKTICK_CLIENT_ID, + clientSecret: process.env.TICKTICK_CLIENT_SECRET, + redirectUri: process.env.TICKTICK_REDIRECT_URI || 'http://localhost:3000/callback', +}; + +if (!config.clientId || !config.clientSecret) { + console.error('❌ Missing TICKTICK_CLIENT_ID or TICKTICK_CLIENT_SECRET'); + console.error('Run: npm run setup-env first'); + process.exit(1); +} + +const auth = new TickTickAuth(config); + +// Create a simple HTTP server to handle OAuth callback +const server = createServer(async (req, res) => { + const urlParts = parse(req.url, true); + + if (urlParts.pathname === '/callback') { + const { code, error } = urlParts.query; + + if (error) { + res.writeHead(400, { 'Content-Type': 'text/html' }); + res.end(` + + +

❌ OAuth Error

+

Error: ${error}

+

Please try again.

+ + + `); + return; + } + + if (code) { + try { + console.log('\n🔄 Exchanging authorization code for tokens...'); + const tokens = await auth.exchangeCodeForToken(code); + + console.log('\n✅ OAuth Success!'); + console.log('📋 Add these to your .env file:'); + console.log(`TICKTICK_ACCESS_TOKEN=${tokens.access_token}`); + console.log(`TICKTICK_REFRESH_TOKEN=${tokens.refresh_token}`); + + res.writeHead(200, { 'Content-Type': 'text/html' }); + res.end(` + + +

✅ OAuth Success!

+

Your TickTick MCP Server is now authenticated.

+

Check your terminal for the access tokens.

+

You can close this window and stop the server (Ctrl+C).

+ + + `); + + console.log('\n🎉 Authentication complete!'); + console.log('You can now stop this server (Ctrl+C) and test your MCP server.'); + + } catch (error) { + console.error('\n❌ Token exchange failed:', error.message); + res.writeHead(500, { 'Content-Type': 'text/html' }); + res.end(` + + +

❌ Token Exchange Failed

+

Error: ${error.message}

+ + + `); + } + } + } else { + res.writeHead(404, { 'Content-Type': 'text/plain' }); + res.end('Not found'); + } +}); + +// Start server +const port = new URL(config.redirectUri).port || 3000; +server.listen(port, () => { + console.log('🚀 TickTick OAuth Helper Started'); + console.log('==============================='); + console.log(`📡 Listening on port ${port}`); + console.log(''); + console.log('🔗 Open this URL in your browser to authenticate:'); + console.log(auth.getAuthorizationUrl()); + console.log(''); + console.log('💡 After authentication, you\'ll get access tokens to add to your .env file'); + console.log('⏹️ Press Ctrl+C to stop this server'); +}); + +// Handle graceful shutdown +process.on('SIGINT', () => { + console.log('\n\n🛑 OAuth helper stopped'); + server.close(); + process.exit(0); +}); \ No newline at end of file diff --git a/simple-build-test.js b/simple-build-test.js new file mode 100644 index 0000000..0a58e2e --- /dev/null +++ b/simple-build-test.js @@ -0,0 +1,84 @@ +const { execSync } = require('child_process'); +const fs = require('fs'); + +console.log('TickTick MCP Server - Simple Build Test'); +console.log('======================================='); + +try { + // Change to project directory + process.chdir('/Users/takashishibata/Desktop/creative-lab/mcp-research/ticktick-mcp-server'); + + console.log('Current directory:', process.cwd()); + console.log(''); + + // Check if package.json exists + if (fs.existsSync('package.json')) { + console.log('✅ package.json found'); + } else { + console.log('❌ package.json not found'); + process.exit(1); + } + + // Check if tsconfig.json exists + if (fs.existsSync('tsconfig.json')) { + console.log('✅ tsconfig.json found'); + } else { + console.log('❌ tsconfig.json not found'); + process.exit(1); + } + + // Check if node_modules exists + if (fs.existsSync('node_modules')) { + console.log('✅ node_modules found'); + } else { + console.log('⚠️ node_modules not found, installing...'); + execSync('npm install', { stdio: 'inherit' }); + } + + console.log('\n1. Running TypeScript type check...'); + console.log('-----------------------------------'); + + try { + const output = execSync('npx tsc --noEmit', { + encoding: 'utf8', + stdio: 'pipe' + }); + console.log('✅ TypeScript type check passed'); + if (output.trim()) { + console.log('Output:', output); + } + } catch (error) { + console.log('❌ TypeScript type check failed:'); + console.log(error.stdout); + console.log(error.stderr); + return; + } + + console.log('\n2. Running build...'); + console.log('-------------------'); + + try { + const output = execSync('npx tsc', { + encoding: 'utf8', + stdio: 'pipe' + }); + console.log('✅ Build completed successfully'); + if (output.trim()) { + console.log('Output:', output); + } + + // Check dist directory + if (fs.existsSync('dist')) { + const files = fs.readdirSync('dist'); + console.log('📁 Built files:', files); + } + + } catch (error) { + console.log('❌ Build failed:'); + console.log(error.stdout); + console.log(error.stderr); + } + +} catch (error) { + console.error('💥 Unexpected error:', error.message); +} \ No newline at end of file diff --git a/simple-type-check.js b/simple-type-check.js new file mode 100644 index 0000000..da38441 --- /dev/null +++ b/simple-type-check.js @@ -0,0 +1,57 @@ +const { exec } = require('child_process'); +const path = require('path'); + +const projectDir = '/Users/takashishibata/Desktop/creative-lab/mcp-research/ticktick-mcp-server'; + +console.log('🔍 Simple TypeScript Type Check'); +console.log('================================'); + +process.chdir(projectDir); +console.log(`📂 Working in: ${process.cwd()}\n`); + +// Run TypeScript type check only +console.log('⚡ Running TypeScript type check (no emit)...'); +exec('npx tsc --noEmit', (error, stdout, stderr) => { + if (error) { + console.log('❌ TypeScript errors found:'); + console.log('---------------------------'); + console.log(stderr); + console.log('\n📊 Error Analysis:'); + + // Count different types of errors + const errorLines = stderr.split('\n').filter(line => line.includes('error TS')); + console.log(`Total errors: ${errorLines.length}`); + + // Group by error type + const errorTypes = {}; + errorLines.forEach(line => { + const match = line.match(/error TS(\d+):/); + if (match) { + const code = match[1]; + errorTypes[code] = (errorTypes[code] || 0) + 1; + } + }); + + console.log('\nError types:'); + Object.entries(errorTypes).forEach(([code, count]) => { + console.log(` TS${code}: ${count} errors`); + }); + + } else { + console.log('✅ No TypeScript errors found!'); + console.log('Ready to build...\n'); + + // If no type errors, try building + console.log('🏗️ Running full build...'); + exec('npm run build', (buildError, buildStdout, buildStderr) => { + if (buildError) { + console.log('❌ Build failed:'); + console.log(buildStderr); + } else { + console.log('✅ Build successful!'); + console.log('📦 Output:'); + console.log(buildStdout); + } + }); + } +}); \ No newline at end of file diff --git a/src/auth/ticktick-api.ts b/src/auth/ticktick-api.ts new file mode 100644 index 0000000..dbd43cf --- /dev/null +++ b/src/auth/ticktick-api.ts @@ -0,0 +1,235 @@ +import axios, { AxiosInstance } from 'axios'; +import { TickTickAuth } from './ticktick-auth.js'; +import { + Task, + Project, + TaskFilter, + APIResponse, +} from '../types/ticktick.js'; +import { ITickTickAPI } from '../types/api-interface.js'; + +export class TickTickAPI implements ITickTickAPI { + private api: AxiosInstance; + private auth: TickTickAuth; + private baseURL = 'https://api.ticktick.com/open/v1'; + + constructor(auth: TickTickAuth) { + this.auth = auth; + this.api = axios.create({ + baseURL: this.baseURL, + timeout: 10000, + }); + + // Add request interceptor to include auth headers + this.api.interceptors.request.use((config) => { + const headers = this.auth.getAuthHeaders(); + Object.assign(config.headers, headers); + return config; + }); + + // Add response interceptor to handle token refresh + this.api.interceptors.response.use( + (response) => response, + async (error) => { + if (error.response?.status === 401) { + try { + await this.auth.refreshAccessToken(); + // Retry the original request + const originalRequest = error.config; + const headers = this.auth.getAuthHeaders(); + Object.assign(originalRequest.headers, headers); + return this.api.request(originalRequest); + } catch (refreshError) { + throw new Error('Authentication failed. Please re-authenticate.'); + } + } + return Promise.reject(error); + } + ); + } + + // Task Management Methods + + /** + * Get all tasks with optional filtering + */ + async getTasks(filter: any = {}): Promise { + try { + const params = new URLSearchParams(); + + if (filter.projectId) params.append('projectId', filter.projectId); + if (filter.completed !== undefined) params.append('completed', filter.completed.toString()); + if (filter.startDate) params.append('startDate', filter.startDate); + if (filter.endDate) params.append('endDate', filter.endDate); + if (filter.limit) params.append('limit', filter.limit.toString()); + if (filter.offset) params.append('offset', filter.offset.toString()); + + const response = await this.api.get(`/task?${params.toString()}`); + return response.data; + } catch (error) { + throw new Error(`Failed to get tasks: ${error}`); + } + } + + /** + * Get task by ID + */ + async getTask(taskId: string): Promise { + try { + const response = await this.api.get(`/task/${taskId}`); + return response.data; + } catch (error) { + throw new Error(`Failed to get task: ${error}`); + } + } + + /** + * Create a new task + */ + async createTask(taskData: any): Promise { + try { + const response = await this.api.post('/task', taskData); + return response.data; + } catch (error) { + throw new Error(`Failed to create task: ${error}`); + } + } + + /** + * Update an existing task + */ + async updateTask(taskData: any): Promise { + try { + const { id, ...updateData } = taskData; + const response = await this.api.post(`/task/${id}`, updateData); + return response.data; + } catch (error) { + throw new Error(`Failed to update task: ${error}`); + } + } + + /** + * Complete a task + */ + async completeTask(taskId: string): Promise { + try { + const response = await this.api.post(`/task/${taskId}/complete`); + return response.data; + } catch (error) { + throw new Error(`Failed to complete task: ${error}`); + } + } + + /** + * Delete a task + */ + async deleteTask(taskId: string): Promise { + try { + await this.api.delete(`/task/${taskId}`); + } catch (error) { + throw new Error(`Failed to delete task: ${error}`); + } + } + + // Project Management Methods + + /** + * Get all projects + */ + async getProjects(): Promise { + try { + const response = await this.api.get('/project'); + return response.data; + } catch (error) { + throw new Error(`Failed to get projects: ${error}`); + } + } + + /** + * Get project by ID + */ + async getProject(projectId: string): Promise { + try { + const response = await this.api.get(`/project/${projectId}`); + return response.data; + } catch (error) { + throw new Error(`Failed to get project: ${error}`); + } + } + + /** + * Create a new project + */ + async createProject(projectData: any): Promise { + try { + const response = await this.api.post('/project', projectData); + return response.data; + } catch (error) { + throw new Error(`Failed to create project: ${error}`); + } + } + + /** + * Update an existing project + */ + async updateProject(projectId: string, projectData: any): Promise { + try { + const response = await this.api.post(`/project/${projectId}`, projectData); + return response.data; + } catch (error) { + throw new Error(`Failed to update project: ${error}`); + } + } + + /** + * Delete a project + */ + async deleteProject(projectId: string): Promise { + try { + await this.api.delete(`/project/${projectId}`); + } catch (error) { + throw new Error(`Failed to delete project: ${error}`); + } + } + + // Convenience Methods + + /** + * Get today's tasks + */ + async getTodayTasks(): Promise { + const today = new Date().toISOString().split('T')[0]; + return this.getTasks({ + startDate: today, + endDate: today, + completed: false, + }); + } + + /** + * Get overdue tasks + */ + async getOverdueTasks(): Promise { + const today = new Date().toISOString().split('T')[0]; + return this.getTasks({ + endDate: today, + completed: false, + }); + } + + /** + * Search tasks by title or content + */ + async searchTasks(query: string, limit?: number): Promise { + try { + const params = new URLSearchParams(); + params.append('q', query); + if (limit) params.append('limit', limit.toString()); + + const response = await this.api.get(`/task/search?${params.toString()}`); + return response.data; + } catch (error) { + throw new Error(`Failed to search tasks: ${error}`); + } + } +} \ No newline at end of file diff --git a/src/auth/ticktick-auth.ts b/src/auth/ticktick-auth.ts new file mode 100644 index 0000000..ea09b12 --- /dev/null +++ b/src/auth/ticktick-auth.ts @@ -0,0 +1,132 @@ +import axios from 'axios'; +import { TickTickConfig, AuthTokens } from '../types/ticktick.js'; + +export class TickTickAuth { + private config: TickTickConfig; + private baseURL = 'https://ticktick.com'; + + constructor(config: TickTickConfig) { + this.config = config; + } + + /** + * Get authorization URL for OAuth flow + */ + getAuthorizationUrl(state?: string): string { + const params = new URLSearchParams({ + client_id: this.config.clientId, + redirect_uri: this.config.redirectUri, + response_type: 'code', + scope: 'tasks:read tasks:write', + }); + + if (state) { + params.append('state', state); + } + + return `${this.baseURL}/oauth/authorize?${params.toString()}`; + } + + /** + * Exchange authorization code for access token + */ + async exchangeCodeForToken(code: string): Promise { + try { + const response = await axios.post( + `${this.baseURL}/oauth/token`, + { + client_id: this.config.clientId, + client_secret: this.config.clientSecret, + redirect_uri: this.config.redirectUri, + grant_type: 'authorization_code', + code, + }, + { + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + } + ); + + const tokens: AuthTokens = response.data; + this.config.accessToken = tokens.access_token; + this.config.refreshToken = tokens.refresh_token; + + return tokens; + } catch (error) { + throw new Error(`Failed to exchange code for token: ${error}`); + } + } + + /** + * Refresh access token using refresh token + */ + async refreshAccessToken(): Promise { + if (!this.config.refreshToken) { + throw new Error('No refresh token available'); + } + + try { + const response = await axios.post( + `${this.baseURL}/oauth/token`, + { + client_id: this.config.clientId, + client_secret: this.config.clientSecret, + grant_type: 'refresh_token', + refresh_token: this.config.refreshToken, + }, + { + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + } + ); + + const tokens: AuthTokens = response.data; + this.config.accessToken = tokens.access_token; + this.config.refreshToken = tokens.refresh_token; + + return tokens; + } catch (error) { + throw new Error(`Failed to refresh token: ${error}`); + } + } + + /** + * Get current access token + */ + getAccessToken(): string | undefined { + return this.config.accessToken; + } + + /** + * Set access token manually + */ + setAccessToken(accessToken: string, refreshToken?: string): void { + this.config.accessToken = accessToken; + if (refreshToken) { + this.config.refreshToken = refreshToken; + } + } + + /** + * Check if user is authenticated + */ + isAuthenticated(): boolean { + return !!this.config.accessToken; + } + + /** + * Get authorization headers for API requests + */ + getAuthHeaders(): Record { + if (!this.config.accessToken) { + throw new Error('No access token available. Please authenticate first.'); + } + + return { + Authorization: `Bearer ${this.config.accessToken}`, + 'Content-Type': 'application/json', + }; + } +} \ No newline at end of file diff --git a/src/config/config-manager.ts b/src/config/config-manager.ts new file mode 100644 index 0000000..e0e9dd9 --- /dev/null +++ b/src/config/config-manager.ts @@ -0,0 +1,245 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import * as os from 'os'; +import { TickTickConfig } from '../types/ticktick.js'; +import { InteractiveSetup, SetupConfig } from '../setup/interactive-setup.js'; + +export class ConfigManager { + private static instance: ConfigManager; + private configPath: string; + private config: TickTickConfig | null = null; + + private constructor() { + const configDir = os.homedir(); + this.configPath = path.join(configDir, '.ticktick-mcp', 'config.json'); + } + + public static getInstance(): ConfigManager { + if (!ConfigManager.instance) { + ConfigManager.instance = new ConfigManager(); + } + return ConfigManager.instance; + } + + /** + * Load configuration from multiple sources in priority order: + * 1. Environment variables + * 2. Saved config file + * 3. Demo mode config + */ + public loadConfig(): TickTickConfig | null { + // Check for demo mode first + if (this.isDemoMode()) { + return this.getDemoConfig(); + } + + // Try environment variables first + const envConfig = this.loadFromEnvironment(); + if (envConfig && this.isValidConfig(envConfig)) { + this.config = envConfig; + return envConfig; + } + + // Try saved config file + const fileConfig = this.loadFromFile(); + if (fileConfig && this.isValidConfig(fileConfig)) { + this.config = fileConfig; + return fileConfig; + } + + return null; + } + + private isDemoMode(): boolean { + return process.env.TICKTICK_DEMO_MODE === 'true' || + process.argv.includes('--demo') || + process.argv.includes('--demo-mode'); + } + + private getDemoConfig(): TickTickConfig { + return { + clientId: 'demo-client-id', + clientSecret: 'demo-client-secret', + redirectUri: 'http://localhost:3000/callback', + accessToken: 'demo-access-token', + refreshToken: 'demo-refresh-token', + }; + } + + private loadFromEnvironment(): TickTickConfig | null { + const clientId = process.env.TICKTICK_CLIENT_ID; + const clientSecret = process.env.TICKTICK_CLIENT_SECRET; + + if (!clientId || !clientSecret) { + return null; + } + + return { + clientId, + clientSecret, + redirectUri: process.env.TICKTICK_REDIRECT_URI || 'http://localhost:3000/callback', + accessToken: process.env.TICKTICK_ACCESS_TOKEN, + refreshToken: process.env.TICKTICK_REFRESH_TOKEN, + }; + } + + private loadFromFile(): TickTickConfig | null { + const savedConfig = InteractiveSetup.loadConfig(); + if (!savedConfig) { + return null; + } + + return { + clientId: savedConfig.clientId, + clientSecret: savedConfig.clientSecret, + redirectUri: savedConfig.redirectUri, + accessToken: savedConfig.accessToken, + refreshToken: savedConfig.refreshToken, + }; + } + + private isValidConfig(config: TickTickConfig): boolean { + return !!(config.clientId && config.clientSecret); + } + + public hasValidConfig(): boolean { + const config = this.loadConfig(); + return config !== null && this.isValidConfig(config); + } + + public hasAuthentication(): boolean { + const config = this.loadConfig(); + return config !== null && !!(config.accessToken && config.refreshToken); + } + + public getConfig(): TickTickConfig | null { + if (!this.config) { + this.config = this.loadConfig(); + } + return this.config; + } + + public async saveTokens(accessToken: string, refreshToken: string): Promise { + const currentConfig = this.loadConfig(); + if (!currentConfig) { + throw new Error('設定が見つかりません。まずセットアップを実行してください。'); + } + + const updatedConfig: SetupConfig = { + clientId: currentConfig.clientId, + clientSecret: currentConfig.clientSecret, + redirectUri: currentConfig.redirectUri, + accessToken, + refreshToken + }; + + // Save to file + const configDir = path.dirname(this.configPath); + if (!fs.existsSync(configDir)) { + fs.mkdirSync(configDir, { recursive: true }); + } + + fs.writeFileSync(this.configPath, JSON.stringify(updatedConfig, null, 2)); + fs.chmodSync(this.configPath, 0o600); // Read/write for owner only + + // Update in-memory config + this.config = { + ...currentConfig, + accessToken, + refreshToken + }; + } + + public getAuthenticationStatus(): { + hasConfig: boolean; + hasAuth: boolean; + isDemoMode: boolean; + configSource: 'environment' | 'file' | 'demo' | 'none'; + } { + const isDemoMode = this.isDemoMode(); + const hasConfig = this.hasValidConfig(); + const hasAuth = this.hasAuthentication(); + + let configSource: 'environment' | 'file' | 'demo' | 'none' = 'none'; + + if (isDemoMode) { + configSource = 'demo'; + } else if (process.env.TICKTICK_CLIENT_ID) { + configSource = 'environment'; + } else if (InteractiveSetup.hasConfig()) { + configSource = 'file'; + } + + return { + hasConfig, + hasAuth, + isDemoMode, + configSource + }; + } + + public displayAuthenticationStatus(): void { + const status = this.getAuthenticationStatus(); + + if (status.isDemoMode) { + console.error('🎭 TickTick MCP Server - デモモード'); + console.error('📊 モックデータを使用(実際のTickTickデータには接続されません)'); + console.error(''); + return; + } + + if (!status.hasConfig) { + console.error('❌ TickTick設定が見つかりません!'); + console.error(''); + console.error('設定を行うには以下のいずれかを実行してください:'); + console.error(''); + console.error('1. 対話式セットアップ(推奨):'); + console.error(' npx @ticktick-ecosystem/mcp-server --setup'); + console.error(''); + console.error('2. 環境変数設定:'); + console.error(' export TICKTICK_CLIENT_ID="your_client_id"'); + console.error(' export TICKTICK_CLIENT_SECRET="your_client_secret"'); + console.error(''); + console.error('3. デモモードでテスト:'); + console.error(' npx @ticktick-ecosystem/mcp-server --demo'); + console.error(''); + return; + } + + console.error('🚀 TickTick MCP Server起動中...'); + console.error(`📁 設定ソース: ${this.getConfigSourceName(status.configSource)}`); + + if (status.hasAuth) { + console.error('✅ TickTick認証: 完了'); + } else { + console.error('⚠️ TickTick認証: 必要'); + console.error(' OAuth認証を完了してください'); + } + + console.error('📡 MCP Server listening on stdio...'); + console.error(''); + } + + private getConfigSourceName(source: string): string { + switch (source) { + case 'environment': return '環境変数'; + case 'file': return '設定ファイル'; + case 'demo': return 'デモモード'; + default: return '不明'; + } + } + + public getSetupInstructions(): void { + console.error('🔧 TickTick MCP Server セットアップ'); + console.error('===================================='); + console.error(''); + console.error('次のコマンドで対話式セットアップを開始してください:'); + console.error(''); + console.error(' npx @ticktick-ecosystem/mcp-server --setup'); + console.error(''); + console.error('または、今すぐデモモードでテストしてみてください:'); + console.error(''); + console.error(' npx @ticktick-ecosystem/mcp-server --demo'); + console.error(''); + } +} \ No newline at end of file diff --git a/src/demo/mock-data.ts b/src/demo/mock-data.ts new file mode 100644 index 0000000..bf3c6b5 --- /dev/null +++ b/src/demo/mock-data.ts @@ -0,0 +1,275 @@ +// Mock data for demo mode +import { Task, Project } from '../types/ticktick.js'; +import { ITickTickAPI } from '../types/api-interface.js'; + +export const mockTasks: Task[] = [ + { + id: 'demo-task-1', + title: 'Complete MCP Server Documentation', + content: 'Write comprehensive documentation for the TickTick MCP server', + dueDate: new Date(Date.now() + 86400000).toISOString(), // Tomorrow + priority: 3, + projectId: 'demo-project-1', + status: 0, + createdTime: new Date().toISOString(), + modifiedTime: new Date().toISOString(), + }, + { + id: 'demo-task-2', + title: 'Review Pull Requests', + content: 'Review and merge pending pull requests', + dueDate: new Date().toISOString(), // Today + priority: 5, + projectId: 'demo-project-1', + status: 0, + createdTime: new Date(Date.now() - 86400000).toISOString(), // Yesterday + modifiedTime: new Date().toISOString(), + }, + { + id: 'demo-task-3', + title: 'Plan Weekly Meeting', + content: 'Prepare agenda for weekly team meeting', + dueDate: new Date(Date.now() - 86400000).toISOString(), // Yesterday (overdue) + priority: 1, + projectId: 'demo-project-2', + status: 0, + createdTime: new Date(Date.now() - 172800000).toISOString(), // 2 days ago + modifiedTime: new Date().toISOString(), + }, + { + id: 'demo-task-4', + title: 'Update Website Content', + content: 'Update the company website with latest product information', + dueDate: new Date(Date.now() + 604800000).toISOString(), // Next week + priority: 2, + projectId: 'demo-project-2', + status: 0, + createdTime: new Date().toISOString(), + modifiedTime: new Date().toISOString(), + }, + { + id: 'demo-task-5', + title: 'Completed Task Example', + content: 'This is an example of a completed task', + dueDate: new Date(Date.now() - 86400000).toISOString(), + priority: 3, + projectId: 'demo-project-1', + status: 1, // Completed + createdTime: new Date(Date.now() - 172800000).toISOString(), + modifiedTime: new Date().toISOString(), + completedTime: new Date().toISOString(), + }, +]; + +export const mockProjects: Project[] = [ + { + id: 'demo-project-1', + name: 'Development Tasks', + color: '#3498db', + sortOrder: 1, + modifiedTime: new Date().toISOString(), + closed: false, + kind: 'project', + }, + { + id: 'demo-project-2', + name: 'Marketing & Content', + color: '#e74c3c', + sortOrder: 2, + modifiedTime: new Date().toISOString(), + closed: false, + kind: 'project', + }, + { + id: 'demo-project-3', + name: 'Personal', + color: '#2ecc71', + sortOrder: 3, + modifiedTime: new Date().toISOString(), + closed: false, + kind: 'project', + }, +]; + +// Helper functions for demo mode +export class MockTickTickAPI implements ITickTickAPI { + private tasks: Task[] = [...mockTasks]; + private projects: Project[] = [...mockProjects]; + + async getTasks(filter: any = {}): Promise { + let filteredTasks = [...this.tasks]; + + if (filter.projectId) { + filteredTasks = filteredTasks.filter(task => task.projectId === filter.projectId); + } + + if (filter.completed !== undefined) { + filteredTasks = filteredTasks.filter(task => + filter.completed ? task.status === 1 : task.status === 0 + ); + } + + if (filter.startDate && filter.endDate) { + filteredTasks = filteredTasks.filter(task => { + if (!task.dueDate) return false; + const taskDate = new Date(task.dueDate); + return taskDate >= new Date(filter.startDate) && taskDate <= new Date(filter.endDate); + }); + } + + if (filter.limit) { + filteredTasks = filteredTasks.slice(0, filter.limit); + } + + return filteredTasks; + } + + async getTask(taskId: string): Promise { + const task = this.tasks.find(t => t.id === taskId); + if (!task) { + throw new Error(`Task not found: ${taskId}`); + } + return task; + } + + async createTask(taskData: any): Promise { + const newTask: Task = { + id: `demo-task-${Date.now()}`, + title: taskData.title, + content: taskData.content || '', + dueDate: taskData.dueDate, + priority: taskData.priority || 0, + projectId: taskData.projectId || 'demo-project-1', + status: 0, + createdTime: new Date().toISOString(), + modifiedTime: new Date().toISOString(), + tags: taskData.tags || [], + }; + + this.tasks.push(newTask); + return newTask; + } + + async updateTask(taskData: any): Promise { + const taskIndex = this.tasks.findIndex(t => t.id === taskData.id); + if (taskIndex === -1) { + throw new Error(`Task not found: ${taskData.id}`); + } + + this.tasks[taskIndex] = { + ...this.tasks[taskIndex], + ...taskData, + modifiedTime: new Date().toISOString(), + }; + + return this.tasks[taskIndex]; + } + + async completeTask(taskId: string): Promise { + const taskIndex = this.tasks.findIndex(t => t.id === taskId); + if (taskIndex === -1) { + throw new Error(`Task not found: ${taskId}`); + } + + this.tasks[taskIndex] = { + ...this.tasks[taskIndex], + status: 1, + completedTime: new Date().toISOString(), + modifiedTime: new Date().toISOString(), + }; + + return this.tasks[taskIndex]; + } + + async deleteTask(taskId: string): Promise { + const taskIndex = this.tasks.findIndex(t => t.id === taskId); + if (taskIndex === -1) { + throw new Error(`Task not found: ${taskId}`); + } + + this.tasks.splice(taskIndex, 1); + } + + async getProjects(): Promise { + return [...this.projects]; + } + + async getProject(projectId: string): Promise { + const project = this.projects.find(p => p.id === projectId); + if (!project) { + throw new Error(`Project not found: ${projectId}`); + } + return project; + } + + async createProject(projectData: any): Promise { + const newProject: Project = { + id: `demo-project-${Date.now()}`, + name: projectData.name, + color: projectData.color || '#3498db', + sortOrder: this.projects.length + 1, + modifiedTime: new Date().toISOString(), + closed: false, + kind: 'project', + }; + + this.projects.push(newProject); + return newProject; + } + + async updateProject(projectId: string, projectData: any): Promise { + const projectIndex = this.projects.findIndex(p => p.id === projectId); + if (projectIndex === -1) { + throw new Error(`Project not found: ${projectId}`); + } + + this.projects[projectIndex] = { + ...this.projects[projectIndex], + ...projectData, + modifiedTime: new Date().toISOString(), + }; + + return this.projects[projectIndex]; + } + + async deleteProject(projectId: string): Promise { + const projectIndex = this.projects.findIndex(p => p.id === projectId); + if (projectIndex === -1) { + throw new Error(`Project not found: ${projectId}`); + } + + this.projects.splice(projectIndex, 1); + } + + // Convenience methods + async getTodayTasks(): Promise { + const today = new Date().toISOString().split('T')[0]; + return this.getTasks({ + startDate: today, + endDate: today, + completed: false, + }); + } + + async getOverdueTasks(): Promise { + const today = new Date().toISOString().split('T')[0]; + return this.tasks.filter(task => { + if (!task.dueDate || task.status === 1) return false; + return new Date(task.dueDate) < new Date(today); + }); + } + + async searchTasks(query: string, limit?: number): Promise { + const lowercaseQuery = query.toLowerCase(); + let results = this.tasks.filter(task => + task.title.toLowerCase().includes(lowercaseQuery) || + (task.content && task.content.toLowerCase().includes(lowercaseQuery)) + ); + + if (limit) { + results = results.slice(0, limit); + } + + return results; + } +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..102ae56 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,106 @@ +#!/usr/bin/env node + +import { TickTickMCPServer } from './server.js'; +import { TickTickConfig } from './types/ticktick.js'; +import { ConfigManager } from './config/config-manager.js'; +import { InteractiveSetup } from './setup/interactive-setup.js'; + +async function main() { + // Check for setup command + if (process.argv.includes('--setup') || process.argv.includes('--configure')) { + console.error('🔧 TickTick MCP Server セットアップを開始します...\n'); + const setup = new InteractiveSetup(); + await setup.run(); + return; + } + + // Check for demo mode + const isDemoMode = process.env.TICKTICK_DEMO_MODE === 'true' || + process.argv.includes('--demo') || + process.argv.includes('--demo-mode'); + + if (isDemoMode) { + console.error('🎭 TickTick MCP Server - デモモード起動中...'); + console.error('📊 モックデータを使用(実際のTickTickデータには接続されません)'); + console.error(''); + + const demoConfig: TickTickConfig = { + clientId: 'demo-client-id', + clientSecret: 'demo-client-secret', + redirectUri: 'http://localhost:3000/callback', + accessToken: 'demo-access-token', + refreshToken: 'demo-refresh-token', + }; + + const server = new TickTickMCPServer(demoConfig, true); // true = demo mode + console.error('✅ デモモード: 準備完了'); + console.error('📡 MCP Server listening on stdio...'); + console.error(''); + + await server.start(); + return; + } + + // Use ConfigManager to load configuration + const configManager = ConfigManager.getInstance(); + const config = configManager.loadConfig(); + + if (!config) { + console.error('❌ TickTick設定が見つかりません!'); + console.error(''); + console.error('設定を行うには以下のいずれかを実行してください:'); + console.error(''); + console.error('1. 対話式セットアップ(推奨):'); + console.error(' npx @ticktick-ecosystem/mcp-server --setup'); + console.error(''); + console.error('2. 環境変数設定:'); + console.error(' export TICKTICK_CLIENT_ID="your_client_id"'); + console.error(' export TICKTICK_CLIENT_SECRET="your_client_secret"'); + console.error(''); + console.error('3. デモモードでテスト:'); + console.error(' npx @ticktick-ecosystem/mcp-server --demo'); + console.error(''); + process.exit(1); + } + + try { + // Display configuration status + configManager.displayAuthenticationStatus(); + + const server = new TickTickMCPServer(config); + + await server.start(); + } catch (error) { + console.error('❌ TickTick MCP Server起動エラー:', error); + console.error(''); + console.error('エラーが発生しました。以下を確認してください:'); + console.error('- 設定ファイルの内容'); + console.error('- ネットワーク接続'); + console.error('- TickTick API認証情報'); + console.error(''); + console.error('再セットアップが必要な場合:'); + console.error(' npx @ticktick-ecosystem/mcp-server --setup'); + console.error(''); + process.exit(1); + } +} + +// Handle graceful shutdown +process.on('SIGINT', () => { + console.error('\n🛑 TickTick MCP Server を終了しています...'); + process.exit(0); +}); + +process.on('SIGTERM', () => { + console.error('\n🛑 TickTick MCP Server を終了しています...'); + process.exit(0); +}); + +main().catch((error) => { + console.error('💥 未処理エラー:', error); + console.error(''); + console.error('問題が継続する場合は、セットアップを再実行してください:'); + console.error(' npx @ticktick-ecosystem/mcp-server --setup'); + console.error(''); + process.exit(1); +}); \ No newline at end of file diff --git a/src/prompts/planning-prompts.ts b/src/prompts/planning-prompts.ts new file mode 100644 index 0000000..c80642f --- /dev/null +++ b/src/prompts/planning-prompts.ts @@ -0,0 +1,281 @@ +import { Prompt } from '@modelcontextprotocol/sdk/types.js'; +import { ITickTickAPI } from '../types/api-interface.js'; + +export class PlanningPrompts { + constructor(private api: ITickTickAPI) {} + + getPrompts(): Prompt[] { + return [ + { + name: 'daily_planning', + description: 'Help plan your daily tasks and priorities', + arguments: [ + { + name: 'focus_areas', + description: 'Specific areas or projects to focus on today', + required: false, + }, + { + name: 'available_hours', + description: 'Number of available working hours today', + required: false, + }, + ], + }, + { + name: 'task_breakdown', + description: 'Break down a complex task into smaller, manageable subtasks', + arguments: [ + { + name: 'main_task', + description: 'The main task or project to break down', + required: true, + }, + { + name: 'deadline', + description: 'Deadline for the main task', + required: false, + }, + { + name: 'complexity', + description: 'Complexity level (simple, medium, complex)', + required: false, + }, + ], + }, + { + name: 'priority_analysis', + description: 'Analyze and suggest priorities for your current tasks', + arguments: [ + { + name: 'project_filter', + description: 'Filter analysis to specific project', + required: false, + }, + { + name: 'time_frame', + description: 'Time frame for analysis (today, week, month)', + required: false, + }, + ], + }, + { + name: 'weekly_review', + description: 'Review your productivity and plan for the upcoming week', + arguments: [ + { + name: 'goals', + description: 'Specific goals for the upcoming week', + required: false, + }, + ], + }, + { + name: 'project_planning', + description: 'Create a comprehensive plan for a new project', + arguments: [ + { + name: 'project_name', + description: 'Name of the new project', + required: true, + }, + { + name: 'project_scope', + description: 'Scope and objectives of the project', + required: true, + }, + { + name: 'timeline', + description: 'Expected timeline for the project', + required: false, + }, + ], + }, + ]; + } + + async getPromptContent(name: string, args: Record = {}): Promise { + try { + switch (name) { + case 'daily_planning': { + const todayTasks = await this.api.getTodayTasks(); + const overdueTasks = await this.api.getOverdueTasks(); + + let prompt = `# Daily Planning Assistant + +## Today's Current Tasks (${todayTasks.length}) +${todayTasks.map(task => `- ${task.title}${task.priority ? ` (Priority: ${task.priority})` : ''}`).join('\n')} + +## Overdue Tasks (${overdueTasks.length}) +${overdueTasks.map(task => `- ${task.title} (Due: ${task.dueDate})`).join('\n')} + +## Planning Guidance +Based on your current tasks, please help me: +1. Prioritize today's tasks effectively +2. Allocate time for each priority task +3. Handle overdue items appropriately +4. Maintain a healthy work-life balance + +`; + + if (args.focus_areas) { + prompt += `## Focus Areas\nToday I want to focus on: ${args.focus_areas}\n\n`; + } + + if (args.available_hours) { + prompt += `## Available Time\nI have ${args.available_hours} hours available for work today.\n\n`; + } + + prompt += `Please provide a structured daily plan with time allocations and priority recommendations.`; + + return prompt; + } + + case 'task_breakdown': { + const mainTask = args.main_task; + const deadline = args.deadline || 'No specific deadline'; + const complexity = args.complexity || 'medium'; + + return `# Task Breakdown Assistant + +## Main Task +**Task:** ${mainTask} +**Deadline:** ${deadline} +**Complexity Level:** ${complexity} + +## Breakdown Request +Please help me break down this task into smaller, actionable subtasks that are: +1. Specific and measurable +2. Appropriately sized (2-4 hours each) +3. Logically sequenced +4. Realistic given the deadline + +## Output Format +Please provide: +- [ ] Subtask 1 (estimated time) +- [ ] Subtask 2 (estimated time) +- [ ] Subtask 3 (estimated time) +... + +Include dependencies between tasks and suggest which subtasks could be done in parallel.`; + } + + case 'priority_analysis': { + const incompleteTasks = await this.api.getTasks({ completed: false }); + const timeFrame = args.time_frame || 'week'; + + let filteredTasks = incompleteTasks; + if (args.project_filter) { + filteredTasks = incompleteTasks.filter(task => + task.projectId === args.project_filter + ); + } + + return `# Priority Analysis Assistant + +## Current Tasks for Analysis (${filteredTasks.length}) +${filteredTasks.map(task => + `- ${task.title}${task.dueDate ? ` (Due: ${task.dueDate})` : ''}${task.priority ? ` (Priority: ${task.priority})` : ''}` + ).join('\n')} + +## Analysis Request +Please analyze these tasks for the ${timeFrame} and provide: + +1. **High Priority** - Tasks that should be done first +2. **Medium Priority** - Tasks that are important but not urgent +3. **Low Priority** - Tasks that can be deferred if needed + +## Criteria for Analysis +Consider: +- Due dates and deadlines +- Task complexity and time requirements +- Dependencies between tasks +- Impact on other projects or people +- Personal/professional goals + +Please provide specific recommendations for task sequencing and time management.`; + } + + case 'weekly_review': { + const completedTasks = await this.api.getTasks({ completed: true }); + const incompleteTasks = await this.api.getTasks({ completed: false }); + + // Filter for tasks from the past week + const weekAgo = new Date(); + weekAgo.setDate(weekAgo.getDate() - 7); + + const recentCompleted = completedTasks.filter(task => + task.completedTime && new Date(task.completedTime) >= weekAgo + ); + + return `# Weekly Review Assistant + +## This Week's Accomplishments (${recentCompleted.length}) +${recentCompleted.map(task => `- ✅ ${task.title}`).join('\n')} + +## Pending Tasks (${incompleteTasks.length}) +${incompleteTasks.slice(0, 10).map(task => `- ⏳ ${task.title}`).join('\n')} +${incompleteTasks.length > 10 ? `... and ${incompleteTasks.length - 10} more` : ''} + +## Review Questions +Please help me reflect on: +1. What went well this week? +2. What challenges did I face? +3. How can I improve my productivity next week? +4. Which pending tasks should be prioritized? + +${args.goals ? `## Goals for Next Week\n${args.goals}\n\n` : ''} + +Please provide a comprehensive weekly review with actionable insights for improvement.`; + } + + case 'project_planning': { + const projects = await this.api.getProjects(); + const projectName = args.project_name; + const projectScope = args.project_scope; + const timeline = args.timeline || 'To be determined'; + + return `# Project Planning Assistant + +## New Project Details +**Project Name:** ${projectName} +**Scope:** ${projectScope} +**Timeline:** ${timeline} + +## Existing Projects (${projects.length}) +${projects.map(project => `- ${project.name}`).join('\n')} + +## Planning Request +Please help me create a comprehensive project plan including: + +1. **Project Breakdown Structure** + - Major phases or milestones + - Key deliverables + - Dependencies and risks + +2. **Task Planning** + - Specific actionable tasks + - Time estimates + - Resource requirements + +3. **Timeline and Scheduling** + - Project phases with dates + - Critical path identification + - Buffer time for uncertainties + +4. **Integration Considerations** + - How this project fits with existing projects + - Resource allocation + - Potential conflicts or synergies + +Please provide a structured project plan that I can implement in TickTick.`; + } + + default: + throw new Error(`Unknown prompt: ${name}`); + } + } catch (error) { + return `Error generating prompt: ${error instanceof Error ? error.message : String(error)}`; + } + } +} \ No newline at end of file diff --git a/src/resources/task-resources.ts b/src/resources/task-resources.ts new file mode 100644 index 0000000..a913840 --- /dev/null +++ b/src/resources/task-resources.ts @@ -0,0 +1,188 @@ +import { Resource } from '@modelcontextprotocol/sdk/types.js'; +import { ITickTickAPI } from '../types/api-interface.js'; + +export class TaskResources { + constructor(private api: ITickTickAPI) {} + + getResources(): Resource[] { + return [ + { + uri: 'ticktick://tasks/today', + name: "Today's Tasks", + description: 'All tasks scheduled for today', + mimeType: 'application/json', + }, + { + uri: 'ticktick://tasks/overdue', + name: 'Overdue Tasks', + description: 'All tasks that are past their due date', + mimeType: 'application/json', + }, + { + uri: 'ticktick://tasks/upcoming', + name: 'Upcoming Tasks', + description: 'Tasks scheduled for the next 7 days', + mimeType: 'application/json', + }, + { + uri: 'ticktick://tasks/all', + name: 'All Tasks', + description: 'All tasks in the account', + mimeType: 'application/json', + }, + { + uri: 'ticktick://tasks/completed', + name: 'Completed Tasks', + description: 'All completed tasks', + mimeType: 'application/json', + }, + { + uri: 'ticktick://tasks/incomplete', + name: 'Incomplete Tasks', + description: 'All incomplete tasks', + mimeType: 'application/json', + }, + { + uri: 'ticktick://projects/all', + name: 'All Projects', + description: 'All projects in the account', + mimeType: 'application/json', + }, + ]; + } + + async getResourceContent(uri: string): Promise { + try { + switch (uri) { + case 'ticktick://tasks/today': { + const tasks = await this.api.getTodayTasks(); + return { + success: true, + data: tasks, + metadata: { + count: tasks.length, + date: new Date().toISOString().split('T')[0], + type: 'today_tasks', + }, + }; + } + + case 'ticktick://tasks/overdue': { + const tasks = await this.api.getOverdueTasks(); + return { + success: true, + data: tasks, + metadata: { + count: tasks.length, + type: 'overdue_tasks', + }, + }; + } + + case 'ticktick://tasks/upcoming': { + const today = new Date(); + const nextWeek = new Date(today); + nextWeek.setDate(today.getDate() + 7); + + const tasks = await this.api.getTasks({ + startDate: today.toISOString().split('T')[0], + endDate: nextWeek.toISOString().split('T')[0], + completed: false, + }); + + return { + success: true, + data: tasks, + metadata: { + count: tasks.length, + startDate: today.toISOString().split('T')[0], + endDate: nextWeek.toISOString().split('T')[0], + type: 'upcoming_tasks', + }, + }; + } + + case 'ticktick://tasks/all': { + const tasks = await this.api.getTasks(); + return { + success: true, + data: tasks, + metadata: { + count: tasks.length, + type: 'all_tasks', + }, + }; + } + + case 'ticktick://tasks/completed': { + const tasks = await this.api.getTasks({ completed: true }); + return { + success: true, + data: tasks, + metadata: { + count: tasks.length, + type: 'completed_tasks', + }, + }; + } + + case 'ticktick://tasks/incomplete': { + const tasks = await this.api.getTasks({ completed: false }); + return { + success: true, + data: tasks, + metadata: { + count: tasks.length, + type: 'incomplete_tasks', + }, + }; + } + + case 'ticktick://projects/all': { + const projects = await this.api.getProjects(); + return { + success: true, + data: projects, + metadata: { + count: projects.length, + type: 'all_projects', + }, + }; + } + + default: + // Handle dynamic URIs like ticktick://projects/{projectId}/tasks + if (uri.startsWith('ticktick://projects/') && uri.endsWith('/tasks')) { + const projectId = uri.split('/')[2]; + const tasks = await this.api.getTasks({ projectId }); + return { + success: true, + data: tasks, + metadata: { + count: tasks.length, + projectId, + type: 'project_tasks', + }, + }; + } + + throw new Error(`Unknown resource URI: ${uri}`); + } + } catch (error) { + return { + success: false, + error: error instanceof Error ? error.message : String(error), + }; + } + } + + // Helper method to create dynamic project task resources + createProjectTaskResource(projectId: string, projectName: string): Resource { + return { + uri: `ticktick://projects/${projectId}/tasks`, + name: `${projectName} Tasks`, + description: `All tasks in the ${projectName} project`, + mimeType: 'application/json', + }; + } +} \ No newline at end of file diff --git a/src/server.ts b/src/server.ts new file mode 100644 index 0000000..03bd028 --- /dev/null +++ b/src/server.ts @@ -0,0 +1,261 @@ +import { Server } from '@modelcontextprotocol/sdk/server/index.js'; +import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; +import { + CallToolRequestSchema, + ListPromptsRequestSchema, + GetPromptRequestSchema, + ListResourcesRequestSchema, + ReadResourceRequestSchema, + ListToolsRequestSchema, +} from '@modelcontextprotocol/sdk/types.js'; + +import { TickTickAuth } from './auth/ticktick-auth.js'; +import { TickTickAPI } from './auth/ticktick-api.js'; +import { TaskTools } from './tools/task-tools.js'; +import { ProjectTools } from './tools/project-tools.js'; +import { TaskResources } from './resources/task-resources.js'; +import { PlanningPrompts } from './prompts/planning-prompts.js'; +import { TickTickConfig } from './types/ticktick.js'; +import { MockTickTickAPI } from './demo/mock-data.js'; +import { ConfigManager } from './config/config-manager.js'; +import { ITickTickAPI } from './types/api-interface.js'; + +export class TickTickMCPServer { + private server: Server; + private auth: TickTickAuth; + private api: ITickTickAPI; + private taskTools: TaskTools; + private projectTools: ProjectTools; + private taskResources: TaskResources; + private planningPrompts: PlanningPrompts; + private isDemoMode: boolean; + private configManager: ConfigManager; + + constructor(config: TickTickConfig, demoMode: boolean = false) { + this.isDemoMode = demoMode; + this.configManager = ConfigManager.getInstance(); + this.server = new Server({ + name: '@ticktick-ecosystem/mcp-server', + version: '1.0.0', + }); + + // Initialize TickTick components + this.auth = new TickTickAuth(config); + + if (this.isDemoMode) { + this.api = new MockTickTickAPI(); + } else { + this.api = new TickTickAPI(this.auth); + } + + this.taskTools = new TaskTools(this.api); + this.projectTools = new ProjectTools(this.api); + this.taskResources = new TaskResources(this.api); + this.planningPrompts = new PlanningPrompts(this.api); + + this.setupHandlers(); + } + + private setupHandlers(): void { + // Tools handlers + this.server.setRequestHandler(ListToolsRequestSchema, async () => { + const taskTools = this.taskTools.getTools(); + const projectTools = this.projectTools.getTools(); + + return { + tools: [...taskTools, ...projectTools], + }; + }); + + this.server.setRequestHandler(CallToolRequestSchema, async (request) => { + const { name, arguments: args } = request.params; + + try { + // Check if user is authenticated (skip for demo mode) + if (!this.isDemoMode && !this.auth.isAuthenticated()) { + return { + content: [ + { + type: 'text', + text: JSON.stringify({ + success: false, + error: '認証が必要です。セットアップを実行してください。', + setup_command: 'npx @ticktick-ecosystem/mcp-server --setup', + authUrl: this.auth.getAuthorizationUrl(), + }), + }, + ], + }; + } + + // Route to appropriate tool handler + let result; + const taskToolNames = this.taskTools.getTools().map(t => t.name); + const projectToolNames = this.projectTools.getTools().map(t => t.name); + + if (taskToolNames.includes(name)) { + result = await this.taskTools.handleToolCall(name, args || {}); + } else if (projectToolNames.includes(name)) { + result = await this.projectTools.handleToolCall(name, args || {}); + } else { + result = { + success: false, + error: `Unknown tool: ${name}`, + }; + } + + return { + content: [ + { + type: 'text', + text: JSON.stringify(result, null, 2), + }, + ], + }; + } catch (error) { + return { + content: [ + { + type: 'text', + text: JSON.stringify({ + success: false, + error: error instanceof Error ? error.message : String(error), + }, null, 2), + }, + ], + }; + } + }); + + // Resources handlers + this.server.setRequestHandler(ListResourcesRequestSchema, async () => { + return { + resources: this.taskResources.getResources(), + }; + }); + + this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => { + const { uri } = request.params; + + try { + if (!this.isDemoMode && !this.auth.isAuthenticated()) { + return { + contents: [ + { + uri, + mimeType: 'application/json', + text: JSON.stringify({ + success: false, + error: '認証が必要です。セットアップを実行してください。', + setup_command: 'npx @ticktick-ecosystem/mcp-server --setup', + }), + }, + ], + }; + } + + const result = await this.taskResources.getResourceContent(uri); + return { + contents: [ + { + uri, + mimeType: 'application/json', + text: JSON.stringify(result, null, 2), + }, + ], + }; + } catch (error) { + return { + contents: [ + { + uri, + mimeType: 'application/json', + text: JSON.stringify({ + success: false, + error: error instanceof Error ? error.message : String(error), + }), + }, + ], + }; + } + }); + + // Prompts handlers + this.server.setRequestHandler(ListPromptsRequestSchema, async () => { + return { + prompts: this.planningPrompts.getPrompts(), + }; + }); + + this.server.setRequestHandler(GetPromptRequestSchema, async (request) => { + const { name, arguments: args } = request.params; + + try { + if (!this.isDemoMode && !this.auth.isAuthenticated()) { + return { + description: '認証が必要です', + messages: [ + { + role: 'user', + content: { + type: 'text', + text: '認証が必要です。セットアップを実行してください: npx @ticktick-ecosystem/mcp-server --setup', + }, + }, + ], + }; + } + + const promptContent = await this.planningPrompts.getPromptContent(name, args || {}); + return { + description: `TickTick ${name} prompt`, + messages: [ + { + role: 'user', + content: { + type: 'text', + text: promptContent, + }, + }, + ], + }; + } catch (error) { + return { + description: 'Error generating prompt', + messages: [ + { + role: 'user', + content: { + type: 'text', + text: `Error: ${error instanceof Error ? error.message : String(error)}`, + }, + }, + ], + }; + } + }); + } + + async start(): Promise { + // Use the built-in stdio transport + const transport = new StdioServerTransport(); + await this.server.connect(transport); + } + + // Helper methods for authentication + getAuthorizationUrl(): string { + return this.auth.getAuthorizationUrl(); + } + + async setAuthorizationCode(code: string): Promise { + await this.auth.exchangeCodeForToken(code); + } + + setAccessToken(accessToken: string, refreshToken?: string): void { + this.auth.setAccessToken(accessToken, refreshToken); + } + + isAuthenticated(): boolean { + return this.auth.isAuthenticated(); + } +} \ No newline at end of file diff --git a/src/setup/interactive-setup.ts b/src/setup/interactive-setup.ts new file mode 100644 index 0000000..49ccea3 --- /dev/null +++ b/src/setup/interactive-setup.ts @@ -0,0 +1,226 @@ +import * as readline from 'readline'; +import * as fs from 'fs'; +import * as path from 'path'; +import * as os from 'os'; +import { TickTickAuth } from '../auth/ticktick-auth.js'; + +export interface SetupConfig { + clientId: string; + clientSecret: string; + redirectUri: string; + accessToken?: string; + refreshToken?: string; +} + +export class InteractiveSetup { + private rl: readline.Interface; + private configDir: string; + private configPath: string; + + constructor() { + this.rl = readline.createInterface({ + input: process.stdin, + output: process.stdout + }); + + this.configDir = path.join(os.homedir(), '.ticktick-mcp'); + this.configPath = path.join(this.configDir, 'config.json'); + } + + private question(prompt: string): Promise { + return new Promise((resolve) => { + this.rl.question(prompt, (answer) => { + resolve(answer.trim()); + }); + }); + } + + private async displayWelcome() { + console.log('\n🎉 TickTick MCP Server セットアップ'); + console.log('=====================================\n'); + console.log('このセットアップでは、TickTick APIの認証情報を設定します。'); + console.log('完了後、Claude DesktopやMCP Inspectorで実際のTickTickデータを使用できます。\n'); + } + + private async displayApiCredentialsInstructions() { + console.log('📋 TickTick API認証情報の取得方法:'); + console.log('-----------------------------------'); + console.log('1. https://developer.ticktick.com/ にアクセス'); + console.log('2. TickTickアカウントでログイン'); + console.log('3. 右上の「Manage Apps」をクリック'); + console.log('4. 「+App Name」をクリックして新しいアプリを作成'); + console.log('5. アプリ名を入力(例:「My MCP Server」)'); + console.log('6. Client IDとClient Secretをコピー'); + console.log('7. OAuth Redirect URLを http://localhost:3000/callback に設定\n'); + + const proceed = await this.question('上記の手順を完了しましたか? (y/N): '); + if (proceed.toLowerCase() !== 'y' && proceed.toLowerCase() !== 'yes') { + console.log('\n手順を完了してから再度実行してください。'); + process.exit(0); + } + console.log(''); + } + + private async collectCredentials(): Promise { + console.log('🔑 API認証情報の入力'); + console.log('---------------------'); + + const clientId = await this.question('Client ID: '); + if (!clientId) { + throw new Error('Client IDは必須です'); + } + + const clientSecret = await this.question('Client Secret: '); + if (!clientSecret) { + throw new Error('Client Secretは必須です'); + } + + const redirectUri = await this.question('Redirect URI (default: http://localhost:3000/callback): ') || 'http://localhost:3000/callback'; + + return { + clientId, + clientSecret, + redirectUri + }; + } + + private async performOAuthFlow(config: SetupConfig): Promise { + console.log('\n🔐 OAuth認証フロー'); + console.log('-------------------'); + + const auth = new TickTickAuth({ + clientId: config.clientId, + clientSecret: config.clientSecret, + redirectUri: config.redirectUri + }); + + const authUrl = auth.getAuthorizationUrl(); + console.log('\n1. 以下のURLをブラウザで開いてください:'); + console.log(` ${authUrl}\n`); + console.log('2. TickTickでアプリを承認'); + console.log('3. リダイレクト後のURLからauthorization codeをコピー'); + console.log(' (例: http://localhost:3000/callback?code=XXXXXX の XXXXXXの部分)\n'); + + const authCode = await this.question('Authorization code: '); + if (!authCode) { + throw new Error('Authorization codeは必須です'); + } + + console.log('\n🔄 アクセストークンを取得中...'); + try { + const tokens = await auth.exchangeCodeForToken(authCode); + + console.log('✅ 認証成功!'); + + return { + ...config, + accessToken: tokens.access_token, + refreshToken: tokens.refresh_token + }; + } catch (error) { + console.error('❌ 認証エラー:', error); + throw new Error('OAuth認証に失敗しました。Client IDとClient Secretを確認してください。'); + } + } + + private async saveConfig(config: SetupConfig) { + console.log('\n💾 設定を保存中...'); + + // Create config directory if it doesn't exist + if (!fs.existsSync(this.configDir)) { + fs.mkdirSync(this.configDir, { recursive: true }); + } + + // Save config to file + fs.writeFileSync(this.configPath, JSON.stringify(config, null, 2)); + + // Set file permissions (readable only by owner) + fs.chmodSync(this.configPath, 0o600); + + console.log(`✅ 設定ファイルを保存しました: ${this.configPath}`); + } + + private async displayCompletion() { + console.log('\n🎉 セットアップ完了!'); + console.log('===================\n'); + console.log('次の手順:'); + console.log('1. TickTick MCP Serverを起動:'); + console.log(' npx @ticktick-ecosystem/mcp-server\n'); + console.log('2. Claude Desktopで使用する場合:'); + console.log(' 設定ファイルに以下を追加:'); + console.log(' {'); + console.log(' "mcpServers": {'); + console.log(' "ticktick": {'); + console.log(' "command": "npx",'); + console.log(' "args": ["@ticktick-ecosystem/mcp-server"]'); + console.log(' }'); + console.log(' }'); + console.log(' }\n'); + console.log('3. MCP Inspectorでテスト:'); + console.log(' npx @modelcontextprotocol/inspector npx @ticktick-ecosystem/mcp-server\n'); + console.log('これで実際のTickTickデータでAI支援のタスク管理が可能になります!'); + } + + public async run(): Promise { + try { + await this.displayWelcome(); + + // Check if config already exists + if (fs.existsSync(this.configPath)) { + console.log('⚠️ 既存の設定が見つかりました。'); + const overwrite = await this.question('設定を上書きしますか? (y/N): '); + if (overwrite.toLowerCase() !== 'y' && overwrite.toLowerCase() !== 'yes') { + console.log('セットアップをキャンセルしました。'); + this.rl.close(); + return; + } + console.log(''); + } + + await this.displayApiCredentialsInstructions(); + + const credentials = await this.collectCredentials(); + + const completeConfig = await this.performOAuthFlow(credentials); + + await this.saveConfig(completeConfig); + + await this.displayCompletion(); + + } catch (error) { + console.error('\n❌ セットアップエラー:', error instanceof Error ? error.message : error); + console.log('\nエラーが発生しました。手順を確認して再度実行してください。'); + process.exit(1); + } finally { + this.rl.close(); + } + } + + public static loadConfig(): SetupConfig | null { + const configDir = path.join(os.homedir(), '.ticktick-mcp'); + const configPath = path.join(configDir, 'config.json'); + + if (!fs.existsSync(configPath)) { + return null; + } + + try { + const configData = fs.readFileSync(configPath, 'utf8'); + return JSON.parse(configData); + } catch (error) { + console.error('設定ファイルの読み込みエラー:', error); + return null; + } + } + + public static hasConfig(): boolean { + const configDir = path.join(os.homedir(), '.ticktick-mcp'); + const configPath = path.join(configDir, 'config.json'); + return fs.existsSync(configPath); + } + + public static getConfigPath(): string { + const configDir = path.join(os.homedir(), '.ticktick-mcp'); + return path.join(configDir, 'config.json'); + } +} \ No newline at end of file diff --git a/src/tools/project-tools.ts b/src/tools/project-tools.ts new file mode 100644 index 0000000..86883f1 --- /dev/null +++ b/src/tools/project-tools.ts @@ -0,0 +1,215 @@ +import { Tool } from '@modelcontextprotocol/sdk/types.js'; +import { z } from 'zod'; +import { ITickTickAPI } from '../types/api-interface.js'; + +// Zod schemas for tool arguments validation +const CreateProjectSchema = z.object({ + name: z.string().describe('Name of the project'), + color: z.string().optional().describe('Color of the project (hex code or color name)'), + groupId: z.string().optional().describe('ID of the group to add project to'), +}); + +const UpdateProjectSchema = z.object({ + projectId: z.string().describe('ID of the project to update'), + name: z.string().optional().describe('New name for the project'), + color: z.string().optional().describe('New color for the project'), +}); + +const ProjectIdSchema = z.object({ + projectId: z.string().describe('ID of the project'), +}); + +export class ProjectTools { + constructor(private api: ITickTickAPI) {} + + getTools(): Tool[] { + return [ + { + name: 'get_projects', + description: 'Get all projects', + inputSchema: { + type: 'object', + properties: {}, + required: [], + }, + }, + { + name: 'get_project', + description: 'Get a specific project by ID', + inputSchema: { + type: 'object', + properties: { + projectId: { + type: 'string', + description: 'ID of the project to retrieve', + }, + }, + required: ['projectId'], + }, + }, + { + name: 'create_project', + description: 'Create a new project', + inputSchema: { + type: 'object', + properties: { + name: { + type: 'string', + description: 'Name of the project', + }, + color: { + type: 'string', + description: 'Color of the project (hex code or color name)', + }, + groupId: { + type: 'string', + description: 'ID of the group to add project to', + }, + }, + required: ['name'], + }, + }, + { + name: 'update_project', + description: 'Update an existing project', + inputSchema: { + type: 'object', + properties: { + projectId: { + type: 'string', + description: 'ID of the project to update', + }, + name: { + type: 'string', + description: 'New name for the project', + }, + color: { + type: 'string', + description: 'New color for the project', + }, + }, + required: ['projectId'], + }, + }, + { + name: 'delete_project', + description: 'Delete a project', + inputSchema: { + type: 'object', + properties: { + projectId: { + type: 'string', + description: 'ID of the project to delete', + }, + }, + required: ['projectId'], + }, + }, + { + name: 'get_project_tasks', + description: 'Get all tasks in a specific project', + inputSchema: { + type: 'object', + properties: { + projectId: { + type: 'string', + description: 'ID of the project', + }, + completed: { + type: 'boolean', + description: 'Filter by completion status', + }, + limit: { + type: 'number', + description: 'Maximum number of tasks to return', + }, + }, + required: ['projectId'], + }, + }, + ]; + } + + async handleToolCall(name: string, args: any): Promise { + try { + switch (name) { + case 'get_projects': { + const projects = await this.api.getProjects(); + return { + success: true, + projects, + count: projects.length, + }; + } + + case 'get_project': { + const validated = ProjectIdSchema.parse(args); + const project = await this.api.getProject(validated.projectId); + return { + success: true, + project, + }; + } + + case 'create_project': { + const validated = CreateProjectSchema.parse(args); + const project = await this.api.createProject(validated); + return { + success: true, + project, + message: `Project "${project.name}" created successfully`, + }; + } + + case 'update_project': { + const validated = UpdateProjectSchema.parse(args); + const { projectId, ...updateData } = validated; + const project = await this.api.updateProject(projectId, updateData); + return { + success: true, + project, + message: `Project "${project.name}" updated successfully`, + }; + } + + case 'delete_project': { + const validated = ProjectIdSchema.parse(args); + await this.api.deleteProject(validated.projectId); + return { + success: true, + message: `Project deleted successfully`, + }; + } + + case 'get_project_tasks': { + const validated = z.object({ + projectId: z.string(), + completed: z.boolean().optional(), + limit: z.number().optional(), + }).parse(args); + + const tasks = await this.api.getTasks({ + projectId: validated.projectId, + completed: validated.completed, + limit: validated.limit, + }); + + return { + success: true, + tasks, + count: tasks.length, + projectId: validated.projectId, + }; + } + + default: + throw new Error(`Unknown tool: ${name}`); + } + } catch (error) { + return { + success: false, + error: error instanceof Error ? error.message : String(error), + }; + } + } +} \ No newline at end of file diff --git a/src/tools/task-tools.ts b/src/tools/task-tools.ts new file mode 100644 index 0000000..b1d7b30 --- /dev/null +++ b/src/tools/task-tools.ts @@ -0,0 +1,331 @@ +import { Tool } from '@modelcontextprotocol/sdk/types.js'; +import { z } from 'zod'; +import { ITickTickAPI } from '../types/api-interface.js'; + +// Zod schemas for tool arguments validation +const CreateTaskSchema = z.object({ + title: z.string().describe('Title of the task'), + content: z.string().optional().describe('Description or content of the task'), + dueDate: z.string().optional().describe('Due date in ISO format (YYYY-MM-DD or YYYY-MM-DDTHH:mm:ss)'), + priority: z.number().min(0).max(5).optional().describe('Priority level (0=None, 1=Low, 3=Medium, 5=High)'), + projectId: z.string().optional().describe('ID of the project to add task to'), + tags: z.array(z.string()).optional().describe('Array of tags for the task'), + allDay: z.boolean().optional().describe('Whether this is an all-day task'), +}); + +const UpdateTaskSchema = z.object({ + taskId: z.string().describe('ID of the task to update'), + title: z.string().optional().describe('New title for the task'), + content: z.string().optional().describe('New description or content'), + dueDate: z.string().optional().describe('New due date in ISO format'), + priority: z.number().min(0).max(5).optional().describe('New priority level'), + projectId: z.string().optional().describe('New project ID'), + tags: z.array(z.string()).optional().describe('New tags array'), + allDay: z.boolean().optional().describe('Whether this is an all-day task'), +}); + +const GetTasksSchema = z.object({ + projectId: z.string().optional().describe('Filter tasks by project ID'), + completed: z.boolean().optional().describe('Filter by completion status'), + limit: z.number().optional().describe('Maximum number of tasks to return'), + startDate: z.string().optional().describe('Start date filter (YYYY-MM-DD)'), + endDate: z.string().optional().describe('End date filter (YYYY-MM-DD)'), +}); + +const TaskIdSchema = z.object({ + taskId: z.string().describe('ID of the task'), +}); + +const SearchTasksSchema = z.object({ + query: z.string().describe('Search query for task title or content'), + limit: z.number().optional().describe('Maximum number of results to return'), +}); + +export class TaskTools { + constructor(private api: ITickTickAPI) {} + + getTools(): Tool[] { + return [ + { + name: 'create_task', + description: 'Create a new task in TickTick', + inputSchema: { + type: 'object', + properties: { + title: { + type: 'string', + description: 'Title of the task', + }, + content: { + type: 'string', + description: 'Description or content of the task', + }, + dueDate: { + type: 'string', + description: 'Due date in ISO format (YYYY-MM-DD or YYYY-MM-DDTHH:mm:ss)', + }, + priority: { + type: 'number', + description: 'Priority level (0=None, 1=Low, 3=Medium, 5=High)', + minimum: 0, + maximum: 5, + }, + projectId: { + type: 'string', + description: 'ID of the project to add task to', + }, + tags: { + type: 'array', + items: { type: 'string' }, + description: 'Array of tags for the task', + }, + allDay: { + type: 'boolean', + description: 'Whether this is an all-day task', + }, + }, + required: ['title'], + }, + }, + { + name: 'get_tasks', + description: 'Get tasks with optional filtering', + inputSchema: { + type: 'object', + properties: { + projectId: { + type: 'string', + description: 'Filter tasks by project ID', + }, + completed: { + type: 'boolean', + description: 'Filter by completion status', + }, + limit: { + type: 'number', + description: 'Maximum number of tasks to return', + }, + startDate: { + type: 'string', + description: 'Start date filter (YYYY-MM-DD)', + }, + endDate: { + type: 'string', + description: 'End date filter (YYYY-MM-DD)', + }, + }, + required: [], + }, + }, + { + name: 'update_task', + description: 'Update an existing task', + inputSchema: { + type: 'object', + properties: { + taskId: { + type: 'string', + description: 'ID of the task to update', + }, + title: { + type: 'string', + description: 'New title for the task', + }, + content: { + type: 'string', + description: 'New description or content', + }, + dueDate: { + type: 'string', + description: 'New due date in ISO format', + }, + priority: { + type: 'number', + description: 'New priority level', + minimum: 0, + maximum: 5, + }, + projectId: { + type: 'string', + description: 'New project ID', + }, + tags: { + type: 'array', + items: { type: 'string' }, + description: 'New tags array', + }, + allDay: { + type: 'boolean', + description: 'Whether this is an all-day task', + }, + }, + required: ['taskId'], + }, + }, + { + name: 'complete_task', + description: 'Mark a task as completed', + inputSchema: { + type: 'object', + properties: { + taskId: { + type: 'string', + description: 'ID of the task to complete', + }, + }, + required: ['taskId'], + }, + }, + { + name: 'delete_task', + description: 'Delete a task', + inputSchema: { + type: 'object', + properties: { + taskId: { + type: 'string', + description: 'ID of the task to delete', + }, + }, + required: ['taskId'], + }, + }, + { + name: 'get_today_tasks', + description: 'Get all tasks scheduled for today', + inputSchema: { + type: 'object', + properties: {}, + required: [], + }, + }, + { + name: 'get_overdue_tasks', + description: 'Get all overdue tasks', + inputSchema: { + type: 'object', + properties: {}, + required: [], + }, + }, + { + name: 'search_tasks', + description: 'Search tasks by title or content', + inputSchema: { + type: 'object', + properties: { + query: { + type: 'string', + description: 'Search query for task title or content', + }, + limit: { + type: 'number', + description: 'Maximum number of results to return', + }, + }, + required: ['query'], + }, + }, + ]; + } + + async handleToolCall(name: string, args: any): Promise { + try { + switch (name) { + case 'create_task': { + const validated = CreateTaskSchema.parse(args); + const task = await this.api.createTask(validated); + return { + success: true, + task, + message: `Task "${task.title}" created successfully`, + }; + } + + case 'get_tasks': { + const validated = GetTasksSchema.parse(args); + const tasks = await this.api.getTasks(validated); + return { + success: true, + tasks, + count: tasks.length, + }; + } + + case 'update_task': { + const validated = UpdateTaskSchema.parse(args); + const { taskId, ...updateData } = validated; + const task = await this.api.updateTask({ id: taskId, ...updateData }); + return { + success: true, + task, + message: `Task "${task.title}" updated successfully`, + }; + } + + case 'complete_task': { + const validated = TaskIdSchema.parse(args); + const task = await this.api.completeTask(validated.taskId); + return { + success: true, + task, + message: `Task completed successfully`, + }; + } + + case 'delete_task': { + const validated = TaskIdSchema.parse(args); + await this.api.deleteTask(validated.taskId); + return { + success: true, + message: `Task deleted successfully`, + }; + } + + case 'get_today_tasks': { + const tasks = await this.api.getTodayTasks(); + return { + success: true, + tasks, + count: tasks.length, + date: new Date().toISOString().split('T')[0], + }; + } + + case 'get_overdue_tasks': { + const tasks = await this.api.getOverdueTasks(); + return { + success: true, + tasks, + count: tasks.length, + }; + } + + case 'search_tasks': { + const validated = SearchTasksSchema.parse(args); + const tasks = await this.api.searchTasks(validated.query); + + // Apply limit if specified + const limitedTasks = validated.limit + ? tasks.slice(0, validated.limit) + : tasks; + + return { + success: true, + tasks: limitedTasks, + count: limitedTasks.length, + query: validated.query, + }; + } + + default: + throw new Error(`Unknown tool: ${name}`); + } + } catch (error) { + return { + success: false, + error: error instanceof Error ? error.message : String(error), + }; + } + } +} \ No newline at end of file diff --git a/src/types/api-interface.ts b/src/types/api-interface.ts new file mode 100644 index 0000000..29b9d02 --- /dev/null +++ b/src/types/api-interface.ts @@ -0,0 +1,21 @@ +import { Task, Project } from './ticktick.js'; + +export interface ITickTickAPI { + // Task operations + getTasks(filter?: any): Promise; + getTask(taskId: string): Promise; + createTask(task: any): Promise; + updateTask(task: any): Promise; + deleteTask(taskId: string): Promise; + completeTask(taskId: string): Promise; + searchTasks(query: string, limit?: number): Promise; + getTodayTasks(): Promise; + getOverdueTasks(): Promise; + + // Project operations + getProjects(): Promise; + getProject(projectId: string): Promise; + createProject(project: any): Promise; + updateProject(projectId: string, projectData: any): Promise; + deleteProject(projectId: string): Promise; +} \ No newline at end of file diff --git a/src/types/ticktick.ts b/src/types/ticktick.ts new file mode 100644 index 0000000..ab58802 --- /dev/null +++ b/src/types/ticktick.ts @@ -0,0 +1,130 @@ +// TickTick API Types +export interface TickTickConfig { + clientId: string; + clientSecret: string; + redirectUri: string; + accessToken?: string; + refreshToken?: string; +} + +export interface Task { + id: string; + title: string; + content?: string; + desc?: string; + allDay?: boolean; + startDate?: string; + dueDate?: string; + timeZone?: string; + reminders?: string[]; + repeat?: string; + priority?: number; + sortOrder?: number; + items?: TaskItem[]; + progress?: number; + assignee?: string; + projectId: string; + tags?: string[]; + kind?: string; + createdTime?: string; + modifiedTime?: string; + completedTime?: string; + status?: number; +} + +export interface TaskItem { + id: string; + title: string; + status: number; + completedTime?: string; + sortOrder: number; +} + +export interface Project { + id: string; + name: string; + color?: string; + inAll?: boolean; + sortOrder?: number; + sortType?: string; + userCount?: number; + etag?: string; + modifiedTime?: string; + closed?: boolean; + muted?: boolean; + transferred?: string; + groupId?: string; + viewMode?: string; + notificationOptions?: { + [key: string]: boolean; + }; + teamId?: string; + permission?: string; + kind?: string; +} + +export interface CreateTaskRequest { + title: string; + content?: string; + desc?: string; + allDay?: boolean; + startDate?: string; + dueDate?: string; + timeZone?: string; + priority?: number; + projectId?: string; + tags?: string[]; + reminders?: string[]; +} + +export interface UpdateTaskRequest { + id: string; + title?: string; + content?: string; + desc?: string; + allDay?: boolean; + startDate?: string; + dueDate?: string; + timeZone?: string; + priority?: number; + projectId?: string; + tags?: string[]; + reminders?: string[]; + status?: number; +} + +export interface CreateProjectRequest { + name: string; + color?: string; + groupId?: string; +} + +export interface UpdateProjectRequest { + id: string; + name?: string; + color?: string; + groupId?: string; +} + +export interface TaskFilter { + projectId?: string; + completed?: boolean; + startDate?: string; + endDate?: string; + limit?: number; + offset?: number; +} + +export interface AuthTokens { + access_token: string; + refresh_token: string; + token_type: string; + expires_in: number; + scope: string; +} + +export interface APIResponse { + data?: T; + error?: string; + status: number; +} \ No newline at end of file diff --git a/test-build.js b/test-build.js new file mode 100644 index 0000000..f13c903 --- /dev/null +++ b/test-build.js @@ -0,0 +1,83 @@ +#!/usr/bin/env node + +const { spawn } = require('child_process'); +const path = require('path'); + +function runCommand(command, args = [], options = {}) { + return new Promise((resolve, reject) => { + console.log(`Running: ${command} ${args.join(' ')}`); + + const child = spawn(command, args, { + stdio: 'inherit', + shell: true, + ...options + }); + + child.on('close', (code) => { + if (code === 0) { + resolve(code); + } else { + reject(new Error(`Command failed with exit code ${code}`)); + } + }); + + child.on('error', (error) => { + reject(error); + }); + }); +} + +async function main() { + const projectDir = process.cwd(); + console.log(`Building TickTick MCP Server in: ${projectDir}`); + console.log('====================================='); + + try { + // Check if node_modules exists + console.log('\n1. Checking dependencies...'); + const fs = require('fs'); + if (!fs.existsSync('node_modules')) { + console.log('node_modules not found. Installing dependencies...'); + await runCommand('npm', ['install']); + } else { + console.log('✅ node_modules exists'); + } + + // Clean dist directory + console.log('\n2. Cleaning build directory...'); + if (fs.existsSync('dist')) { + await runCommand('rm', ['-rf', 'dist']); + } + console.log('✅ Build directory cleaned'); + + // Run TypeScript compilation + console.log('\n3. Running TypeScript compilation...'); + await runCommand('npx', ['tsc', '--noEmit'], { cwd: projectDir }); + console.log('✅ TypeScript type checking passed'); + + console.log('\n4. Building project...'); + await runCommand('npx', ['tsc'], { cwd: projectDir }); + console.log('✅ Build completed successfully'); + + // Check if dist was created + if (fs.existsSync('dist')) { + console.log('\n5. Verifying build output...'); + const distFiles = fs.readdirSync('dist'); + console.log('Built files:', distFiles); + console.log('✅ Build verification complete'); + } + + console.log('\n🎉 Build successful!'); + console.log('====================================='); + + } catch (error) { + console.error('\n❌ Build failed!'); + console.error('Error:', error.message); + console.error('====================================='); + process.exit(1); + } +} + +if (require.main === module) { + main(); +} \ No newline at end of file diff --git a/test-compile.ts b/test-compile.ts new file mode 100644 index 0000000..d29a3a8 --- /dev/null +++ b/test-compile.ts @@ -0,0 +1,17 @@ +// Simple test file to check TypeScript compilation +import { TickTickMCPServer } from './src/server.js'; +import { TickTickConfig } from './src/types/ticktick.js'; + +// Test basic imports +console.log('TypeScript imports working'); + +// Test config type +const testConfig: TickTickConfig = { + clientId: 'test', + clientSecret: 'test', + redirectUri: 'test' +}; + +console.log('Config type working'); + +export {}; \ No newline at end of file diff --git a/test-demo.js b/test-demo.js new file mode 100644 index 0000000..413489a --- /dev/null +++ b/test-demo.js @@ -0,0 +1,49 @@ +#!/usr/bin/env node + +// Simple test script to verify demo mode functionality +import { spawn } from 'child_process'; +import { setTimeout } from 'timers/promises'; + +console.log('🧪 Testing TickTick MCP Server Demo Mode...\n'); + +// Start the server in demo mode +const server = spawn('node', ['dist/index.js', '--demo'], { + stdio: ['pipe', 'pipe', 'inherit'], + env: { ...process.env, TICKTICK_DEMO_MODE: 'true' } +}); + +// Send a simple MCP request to list tools +const mcpRequest = { + jsonrpc: '2.0', + id: 1, + method: 'tools/list' +}; + +setTimeout(1000).then(() => { + console.log('📤 Sending tools/list request...'); + server.stdin.write(JSON.stringify(mcpRequest) + '\n'); + + setTimeout(2000).then(() => { + console.log('✅ Demo mode test completed'); + server.kill(); + process.exit(0); + }); +}); + +server.stdout.on('data', (data) => { + try { + const response = JSON.parse(data.toString()); + console.log('📥 Server response:', JSON.stringify(response, null, 2)); + } catch (e) { + console.log('📥 Server output:', data.toString()); + } +}); + +server.on('error', (error) => { + console.error('❌ Server error:', error); + process.exit(1); +}); + +server.on('exit', (code) => { + console.log(`\n🏁 Server exited with code: ${code}`); +}); \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..0f53fb5 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "node", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "allowSyntheticDefaultImports": true, + "declaration": true, + "outDir": "./dist", + "rootDir": "./src", + "removeComments": true, + "sourceMap": true + }, + "include": [ + "src/**/*" + ], + "exclude": [ + "node_modules", + "dist", + "**/*.test.ts" + ] +} \ No newline at end of file