diff --git a/.env.example b/.env.example index dccc6d3..84d35a2 100644 --- a/.env.example +++ b/.env.example @@ -7,11 +7,6 @@ DATABASE_URL=your_postgresql_database_url # AI Chat Service GROQ_API_KEY=your_groq_api_key -# Namecheap Domain Management -NAMECHEAP_API_USER=your_namecheap_api_user -NAMECHEAP_API_KEY=your_namecheap_api_key -NAMECHEAP_USERNAME=your_namecheap_username - # Cloud Provider Credentials (Optional) AZURE_CLIENT_ID=your_azure_client_id AZURE_CLIENT_SECRET=your_azure_client_secret @@ -23,4 +18,4 @@ GITHUB_PERSONAL_ACCESS_TOKEN=your_github_token # Production Environment NODE_ENV=production -PORT=5000 \ No newline at end of file +PORT=5000 diff --git a/.env.namecheap b/.env.namecheap deleted file mode 100644 index c81184b..0000000 --- a/.env.namecheap +++ /dev/null @@ -1,30 +0,0 @@ -# Environment Variables for Namecheap Hosting -# Create this file as .env in your hosting root directory - -# Domain Configuration -DOMAIN=instantiate.dev -ENVIRONMENT=production - -# Database (if using MySQL from Namecheap) -DB_HOST=localhost -DB_NAME=your_database_name -DB_USER=your_database_user -DB_PASS=your_database_password - -# API Keys -GROQ_API_KEY=your_groq_api_key_here -NAMECHEAP_API_USER=your_namecheap_api_user -NAMECHEAP_API_KEY=your_namecheap_api_key -NAMECHEAP_USERNAME=your_namecheap_username - -# Security -JWT_SECRET=your_random_jwt_secret -ENCRYPTION_KEY=your_encryption_key - -# External Services (Optional) -GITHUB_TOKEN=your_github_token -MONITORING_KEY=your_monitoring_key - -# Namecheap Specific -CPANEL_URL=https://cpanel.your_domain.com -HOSTING_TYPE=shared # or vps, dedicated diff --git a/.env.production b/.env.production index cd7e70f..fbfc195 100644 --- a/.env.production +++ b/.env.production @@ -12,11 +12,6 @@ DATABASE_URL=your_production_database_url # AI Chat Service GROQ_API_KEY=your_groq_api_key -# Namecheap Domain Management -NAMECHEAP_API_USER=your_namecheap_api_user -NAMECHEAP_API_KEY=your_namecheap_api_key -NAMECHEAP_USERNAME=your_namecheap_username - # Security JWT_SECRET=your_jwt_secret_key ENCRYPTION_KEY=your_encryption_key @@ -27,4 +22,4 @@ MIXPANEL_TOKEN=your_mixpanel_token # Monitoring (Optional) SENTRY_DSN=your_sentry_dsn -UPTIME_ROBOT_API_KEY=your_uptime_robot_key \ No newline at end of file +UPTIME_ROBOT_API_KEY=your_uptime_robot_key diff --git a/DEPLOY.html b/DEPLOY.html index ffa0e7c..b391213 100644 --- a/DEPLOY.html +++ b/DEPLOY.html @@ -116,7 +116,7 @@

Step 3: Environment Variables

@@ -130,4 +130,4 @@

🔒 SSL Certificate

- \ No newline at end of file + diff --git a/NAMECHEAP_CONFIG.md b/NAMECHEAP_CONFIG.md deleted file mode 100644 index cccba8a..0000000 --- a/NAMECHEAP_CONFIG.md +++ /dev/null @@ -1,22 +0,0 @@ -# Namecheap Hosting Configuration - -## Manual Upload Configuration -This application is configured for manual upload to Namecheap hosting. - -### Upload Instructions -1. Build: npm run build -2. Upload: client/dist/* to public_html/ -3. Config: Upload .htaccess to root -4. Environment: Create .env with API keys - -### Files for Namecheap -- client/dist/* → public_html/ -- .htaccess → public_html/ -- .env → public_html/ - -### Domain Configuration -- DNS: Already configured in Namecheap -- SSL: Auto-provisions via hosting provider -- Domain: instantiate.dev - -No Netlify configuration needed for manual deployment. diff --git a/NAMECHEAP_DEPLOYMENT.md b/NAMECHEAP_DEPLOYMENT.md deleted file mode 100644 index 254a635..0000000 --- a/NAMECHEAP_DEPLOYMENT.md +++ /dev/null @@ -1,55 +0,0 @@ -# Namecheap Hosting Deployment Guide - -## Upload Instructions - -1. **Build the Application** - - Run `npm install` to install dependencies - - Run `npm run build` to create production build - - Upload contents of `client/dist` folder to your domain's public_html directory - -2. **File Structure on Namecheap** - ``` - public_html/ - ├── index.html (main app file) - ├── assets/ (CSS, JS, images) - ├── api/ (API routes - needs PHP or Node.js hosting) - └── .htaccess (URL rewriting) - ``` - -3. **Server Requirements** - - Node.js hosting (if available) OR - - PHP hosting with custom API endpoints OR - - Static hosting with external API - -4. **Environment Configuration** - Create these files in your hosting: - - `.env` with your API keys - - Database configuration - - Domain settings - -## Files Included -- Complete source code -- Build configuration -- Server files -- Database schema -- Environment templates - -## Deployment Options - -### Option A: Full Stack (Node.js hosting required) -Upload entire application with server - -### Option B: Frontend Only (Static hosting) -Upload only client/dist folder contents - -### Option C: Hybrid (Recommended) -Frontend on Namecheap + Backend on external service - -## Post-Upload Steps -1. Configure environment variables -2. Set up database connections -3. Configure DNS (already done) -4. Test all functionality -5. Enable SSL certificate - -Your instantiate.dev domain is already configured to point to Namecheap hosting. diff --git a/NAMECHEAP_INTEGRATION.md b/NAMECHEAP_INTEGRATION.md deleted file mode 100644 index e1af018..0000000 --- a/NAMECHEAP_INTEGRATION.md +++ /dev/null @@ -1,99 +0,0 @@ -# Namecheap Domain Management Integration - -## Overview -Complete domain management integration with Namecheap API enabling automated domain configuration, DNS management, and SSL provisioning directly from your multi-cloud platform. - -## Features - -### Domain Management -- View all registered domains with expiration dates -- Domain status monitoring and alerts -- Auto-renewal configuration -- Domain locking/unlocking -- WhoisGuard management - -### DNS Management -- Complete DNS record management (A, AAAA, CNAME, MX, TXT, NS, SRV) -- Real-time DNS propagation monitoring -- Bulk DNS record operations -- Subdomain creation and management -- DNS template system for common configurations - -### Domain Search & Registration -- Real-time domain availability checking -- Premium domain detection -- Bulk domain search capabilities -- Price comparison and recommendations -- Domain suggestion engine - -### Cloud Integration -- Automatic Cloudflare setup -- AWS Route 53 integration -- Azure DNS integration -- Google Cloud DNS support -- Multi-cloud DNS failover - -### SSL Certificate Management -- Automatic SSL certificate provisioning -- Certificate renewal automation -- Multi-domain and wildcard certificates -- SSL health monitoring -- Certificate deployment tracking - -## API Endpoints - -### Domain Operations -- `GET /api/namecheap/domains` - List all domains -- `GET /api/namecheap/domains/:domain/info` - Get domain details -- `POST /api/namecheap/domains/:domain/renew` - Renew domain -- `POST /api/namecheap/domains/:domain/auto-renew` - Enable auto-renewal - -### DNS Operations -- `GET /api/namecheap/dns/:domain` - Get DNS records -- `POST /api/namecheap/dns` - Add DNS record -- `PUT /api/namecheap/dns/:domain` - Update DNS records -- `DELETE /api/namecheap/dns/:domain/:record` - Delete DNS record - -### Domain Search -- `GET /api/namecheap/check/:domains` - Check domain availability -- `POST /api/namecheap/search` - Advanced domain search - -### Cloud Integration -- `POST /api/namecheap/domains/:domain/cloudflare` - Setup Cloudflare -- `POST /api/namecheap/domains/:domain/aws` - Connect to AWS Route 53 -- `POST /api/namecheap/domains/:domain/azure` - Connect to Azure DNS - -## Security Features -- API key encryption and secure storage -- IP whitelisting for API access -- Rate limiting and request throttling -- Audit logging for all domain operations -- Two-factor authentication support - -## Automation Capabilities -- Automatic deployment domain setup -- DNS record synchronization across clouds -- SSL certificate auto-renewal -- Domain expiration monitoring and alerts -- Backup DNS configuration - -## Dashboard Features -- Real-time domain status monitoring -- DNS propagation visualization -- Cost tracking and optimization -- Performance analytics -- Security compliance reporting - -## Environment Variables Required -- `NAMECHEAP_API_USER` - Your Namecheap API username -- `NAMECHEAP_API_KEY` - Your Namecheap API key -- `NAMECHEAP_USERNAME` - Your Namecheap account username - -## Integration Benefits -1. **Unified Management** - Manage domains alongside cloud infrastructure -2. **Automated Setup** - Automatic domain configuration for new deployments -3. **Cost Optimization** - Domain renewal alerts and bulk management -4. **Security Enhancement** - Automated SSL provisioning and monitoring -5. **Performance Monitoring** - DNS performance tracking and optimization - -Generated: 2025-06-09T23:44:35.504Z \ No newline at end of file diff --git a/NETLIFY_DEPLOYMENT.md b/NETLIFY_DEPLOYMENT.md deleted file mode 100644 index 13fd7ce..0000000 --- a/NETLIFY_DEPLOYMENT.md +++ /dev/null @@ -1,97 +0,0 @@ -# Deploy to Netlify - Step by Step Guide - -## Quick Start (5 minutes) - -### Step 1: Access Netlify -1. Go to https://netlify.com -2. Sign in with GitHub account -3. Click "New site from Git" - -### Step 2: Connect Repository -1. Select "GitHub" as your Git provider -2. Search for and select: **Imole-cloud/-Instantiate.dev** -3. Choose the **main** branch - -### Step 3: Configure Build Settings -Netlify will auto-detect these settings (already configured): -- **Build command:** `npm run build` -- **Publish directory:** `dist` -- **Node version:** 18 - -### Step 4: Add Environment Variables -In Site Settings > Environment Variables, add: - -**Required Variables:** -``` -DATABASE_URL=postgresql://neondb_owner:npg_FE5lzguCWNQ7@ep-plain-cake-a5dj6iy2.us-east-2.aws.neon.tech/neondb?sslmode=require -GROQ_API_KEY=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 -NODE_ENV=production -``` - -**Optional Cloud Provider Variables (add as needed):** -``` -AWS_ACCESS_KEY_ID=your_aws_key -AWS_SECRET_ACCESS_KEY=your_aws_secret -AZURE_CLIENT_ID=your_azure_client_id -AZURE_CLIENT_SECRET=your_azure_secret -``` - -### Step 5: Deploy -1. Click "Deploy site" -2. Wait for build to complete (2-3 minutes) -3. Your platform will be live at: https://your-site-name.netlify.app - -## What You Get After Deployment - -Your live multi-cloud platform will include: - -### Dashboard Features -- Real-time analytics from 11 cloud providers -- Interactive 3D cloud architecture visualization -- Live performance monitoring and health scores -- Cost analysis with trend tracking -- Security assessment and compliance reports - -### AI Assistant -- Intelligent deployment guidance -- Automated troubleshooting -- Infrastructure code generation -- Smart optimization recommendations - -### Multi-Cloud Integration -- AWS, Azure, Google Cloud, Alibaba Cloud -- IBM Cloud, Oracle Cloud, DigitalOcean -- Linode, Huawei Cloud, Tencent Cloud, Netlify -- Unified resource management interface - -## Troubleshooting - -### Build Fails -- Check build logs in Netlify dashboard -- Ensure all environment variables are set -- Verify Node version is 18+ - -### Missing Data -- Add cloud provider API keys for full functionality -- Database connection required for deployment tracking -- Groq API key needed for AI assistant - -### Performance Issues -- Enable Netlify's CDN and caching -- Consider upgrading to Pro plan for better performance -- Monitor function execution times - -## Custom Domain (Optional) - -1. Go to Site Settings > Domain management -2. Add custom domain -3. Configure DNS records as shown -4. Enable HTTPS (automatic) - -## Support - -- Repository: https://github.com/Imole-cloud/-Instantiate.dev -- Issues: Create GitHub issue for bugs -- Features: Submit feature requests via GitHub - -Your multi-cloud platform is production-ready with enterprise-grade features! \ No newline at end of file diff --git a/api/index.php b/api/index.php index 7ea19bb..7012c64 100644 --- a/api/index.php +++ b/api/index.php @@ -20,7 +20,7 @@ echo json_encode([ 'status' => 'ok', 'timestamp' => date('c'), - 'environment' => 'namecheap_hosting' + 'environment' => 'production' ]); break; @@ -38,4 +38,4 @@ echo json_encode(['error' => 'Endpoint not found']); break; } -?> \ No newline at end of file +?> diff --git a/functions/api.ts b/functions/api.ts deleted file mode 100644 index 99d6d42..0000000 --- a/functions/api.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { Handler } from '@netlify/functions'; -import { registerRoutes } from '../../server/routes.js'; -import express from 'express'; - -const app = express(); - -let routesInitialized = false; - -async function initializeRoutes() { - if (!routesInitialized) { - await registerRoutes(app); - routesInitialized = true; - } -} - -export const handler: Handler = async (event, context) => { - await initializeRoutes(); - - // Handle API requests through Express app - return new Promise((resolve, reject) => { - const req = { - method: event.httpMethod, - url: event.path, - headers: event.headers, - body: event.body - }; - - const res = { - statusCode: 200, - headers: {}, - body: '', - status: (code) => { res.statusCode = code; return res; }, - json: (data) => { res.body = JSON.stringify(data); return res; }, - send: (data) => { res.body = data; return res; }, - setHeader: (key, value) => { res.headers[key] = value; } - }; - - try { - app(req, res); - resolve({ - statusCode: res.statusCode, - headers: res.headers, - body: res.body - }); - } catch (error) { - reject(error); - } - }); -}; diff --git a/netlify.toml b/netlify.toml deleted file mode 100644 index 55670ba..0000000 --- a/netlify.toml +++ /dev/null @@ -1,11 +0,0 @@ -[build] - publish = "dist" - command = "npm run build" - -[build.environment] - NODE_VERSION = "18" - -[[redirects]] - from = "/*" - to = "/index.html" - status = 200 diff --git a/package-lock.json b/package-lock.json index 3610041..21ebe43 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,6 @@ "version": "1.0.0", "dependencies": { "@hookform/resolvers": "^3.10.0", - "@netlify/functions": "^2.4.0", "@radix-ui/react-accordion": "^1.2.4", "@radix-ui/react-alert-dialog": "^1.1.7", "@radix-ui/react-avatar": "^1.1.4", @@ -26,10 +25,14 @@ "@radix-ui/react-toast": "^1.2.14", "@radix-ui/react-tooltip": "^1.1.7", "@tanstack/react-query": "^5.59.0", + "@types/aws-sdk": "^0.0.42", + "@types/node-fetch": "^2.6.12", + "aws-sdk": "^2.1692.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "express": "^4.18.2", "lucide-react": "^0.454.0", + "node-fetch": "^3.3.2", "react": "^18.3.1", "react-dom": "^18.3.1", "react-hook-form": "^7.54.0", @@ -860,40 +863,6 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@netlify/functions": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@netlify/functions/-/functions-2.8.2.tgz", - "integrity": "sha512-DeoAQh8LuNPvBE4qsKlezjKj0PyXDryOFJfJKo3Z1qZLKzQ21sT314KQKPVjfvw6knqijj+IO+0kHXy/TJiqNA==", - "license": "MIT", - "dependencies": { - "@netlify/serverless-functions-api": "1.26.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@netlify/node-cookies": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@netlify/node-cookies/-/node-cookies-0.1.0.tgz", - "integrity": "sha512-OAs1xG+FfLX0LoRASpqzVntVV/RpYkgpI0VrUnw2u0Q1qiZUzcPffxRK8HF3gc4GjuhG5ahOEMJ9bswBiZPq0g==", - "license": "MIT", - "engines": { - "node": "^14.16.0 || >=16.0.0" - } - }, - "node_modules/@netlify/serverless-functions-api": { - "version": "1.26.1", - "resolved": "https://registry.npmjs.org/@netlify/serverless-functions-api/-/serverless-functions-api-1.26.1.tgz", - "integrity": "sha512-q3L9i3HoNfz0SGpTIS4zTcKBbRkxzCRpd169eyiTuk3IwcPC3/85mzLHranlKo2b+HYT0gu37YxGB45aD8A3Tw==", - "license": "MIT", - "dependencies": { - "@netlify/node-cookies": "^0.1.0", - "urlpattern-polyfill": "8.0.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2281,6 +2250,15 @@ "react": "^18 || ^19" } }, + "node_modules/@types/aws-sdk": { + "version": "0.0.42", + "resolved": "https://registry.npmjs.org/@types/aws-sdk/-/aws-sdk-0.0.42.tgz", + "integrity": "sha512-zIgLukZrf0/s+oAKxLMHgZFDDjDpuJ95hbE9DiNGrmNGNM7odIt99rHLWVwnOYdF0TNjF0reQeL/mcadAIqljg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -2337,12 +2315,21 @@ "version": "22.15.30", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.30.tgz", "integrity": "sha512-6Q7lr06bEHdlfplU6YRbgG1SFBdlsfNC4/lX+SkhiTs0cpJkOElmWls8PxDFv4yY/xKb8Y6SO0OmSX4wgqTZbA==", - "dev": true, "license": "MIT", "dependencies": { "undici-types": "~6.21.0" } }, + "node_modules/@types/node-fetch": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.12.tgz", + "integrity": "sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "form-data": "^4.0.0" + } + }, "node_modules/@types/prop-types": { "version": "15.7.14", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", @@ -2477,6 +2464,12 @@ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "license": "MIT" }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, "node_modules/autoprefixer": { "version": "10.4.21", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", @@ -2515,6 +2508,52 @@ "postcss": "^8.1.0" } }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/aws-sdk": { + "version": "2.1692.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1692.0.tgz", + "integrity": "sha512-x511uiJ/57FIsbgUe5csJ13k3uzu25uWQE+XqfBis/sB0SFoiElJWXRkgEAUh0U6n40eT3ay5Ue4oPkRMu1LYw==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "buffer": "4.9.2", + "events": "1.1.1", + "ieee754": "1.1.13", + "jmespath": "0.16.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "util": "^0.12.4", + "uuid": "8.0.0", + "xml2js": "0.6.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/aws-sdk/node_modules/uuid": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", + "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -2522,6 +2561,26 @@ "dev": true, "license": "MIT" }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "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/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -2630,6 +2689,17 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "license": "MIT", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -2639,6 +2709,24 @@ "node": ">= 0.8" } }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", @@ -2778,6 +2866,18 @@ "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/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -2866,6 +2966,15 @@ "devOptional": true, "license": "MIT" }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, "node_modules/debug": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", @@ -2884,6 +2993,32 @@ } } }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/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", @@ -3003,6 +3138,21 @@ "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.21.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", @@ -3067,6 +3217,15 @@ "node": ">= 0.6" } }, + "node_modules/events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==", + "license": "MIT", + "engines": { + "node": ">=0.4.x" + } + }, "node_modules/express": { "version": "4.21.2", "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", @@ -3168,6 +3327,29 @@ "reusify": "^1.0.4" } }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -3214,6 +3396,21 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/foreground-child": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", @@ -3231,6 +3428,34 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/form-data": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz", + "integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==", + "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/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "license": "MIT", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -3399,6 +3624,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", @@ -3411,6 +3648,21 @@ "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", @@ -3451,6 +3703,12 @@ "node": ">=0.10.0" } }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", + "license": "BSD-3-Clause" + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -3466,6 +3724,22 @@ "node": ">= 0.10" } }, + "node_modules/is-arguments": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -3479,6 +3753,18 @@ "node": ">=8" } }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-core-module": { "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", @@ -3515,6 +3801,24 @@ "node": ">=8" } }, + "node_modules/is-generator-function": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", + "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-proto": "^1.0.0", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -3538,6 +3842,45 @@ "node": ">=0.12.0" } }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -3571,6 +3914,15 @@ "jiti": "bin/jiti.js" } }, + "node_modules/jmespath": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", + "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==", + "license": "Apache-2.0", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -3825,6 +4177,44 @@ "node": ">= 0.6" } }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, "node_modules/node-releases": { "version": "2.0.19", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", @@ -3999,6 +4389,15 @@ "node": ">= 6" } }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/postcss": { "version": "8.5.4", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.4.tgz", @@ -4162,6 +4561,12 @@ "node": ">= 0.10" } }, + "node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==", + "license": "MIT" + }, "node_modules/qs": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", @@ -4177,6 +4582,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "engines": { + "node": ">=0.4.x" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -4490,12 +4904,35 @@ ], "license": "MIT" }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/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/sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==", + "license": "ISC" + }, "node_modules/scheduler": { "version": "0.23.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", @@ -4578,6 +5015,23 @@ "node": ">= 0.8.0" } }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -4998,7 +5452,6 @@ "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": { @@ -5041,11 +5494,15 @@ "browserslist": ">= 4.21.0" } }, - "node_modules/urlpattern-polyfill": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-8.0.2.tgz", - "integrity": "sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ==", - "license": "MIT" + "node_modules/url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==", + "license": "MIT", + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } }, "node_modules/use-callback-ref": { "version": "1.3.3", @@ -5099,6 +5556,19 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -5197,6 +5667,15 @@ } } }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -5213,6 +5692,27 @@ "node": ">= 8" } }, + "node_modules/which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/wouter": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/wouter/-/wouter-3.7.1.tgz", @@ -5346,6 +5846,28 @@ } } }, + "node_modules/xml2js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", diff --git a/package.json b/package.json index c71978a..8af2e3f 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,6 @@ }, "dependencies": { "@hookform/resolvers": "^3.10.0", - "@netlify/functions": "^2.4.0", "@radix-ui/react-accordion": "^1.2.4", "@radix-ui/react-alert-dialog": "^1.1.7", "@radix-ui/react-avatar": "^1.1.4", @@ -26,10 +25,14 @@ "@radix-ui/react-toast": "^1.2.14", "@radix-ui/react-tooltip": "^1.1.7", "@tanstack/react-query": "^5.59.0", + "@types/aws-sdk": "^0.0.42", + "@types/node-fetch": "^2.6.12", + "aws-sdk": "^2.1692.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "express": "^4.18.2", "lucide-react": "^0.454.0", + "node-fetch": "^3.3.2", "react": "^18.3.1", "react-dom": "^18.3.1", "react-hook-form": "^7.54.0", diff --git a/scripts/setup-netlify-env.sh b/scripts/setup-netlify-env.sh deleted file mode 100644 index 895f937..0000000 --- a/scripts/setup-netlify-env.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash -# Netlify Environment Variables Setup Script - -echo "Setting up Netlify environment variables..." - -# Required variables (already configured in Replit) -netlify env:set DATABASE_URL "postgresql://neondb_owner:npg_FE5lzguCWNQ7@ep-plain-cake-a5dj6iy2.us-east-2.aws.neon.tech/neondb?sslmode=require" -netlify env:set GROQ_API_KEY "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" - -# Application settings -netlify env:set NODE_ENV "production" -netlify env:set PORT "5000" - -echo "✅ Core environment variables configured" -echo "Add cloud provider credentials manually in Netlify dashboard as needed" -echo "Your platform is ready for deployment!" \ No newline at end of file diff --git a/server/ai-chat-service.ts b/server/ai-chat-service.ts index 391d851..dfd6280 100644 --- a/server/ai-chat-service.ts +++ b/server/ai-chat-service.ts @@ -7,7 +7,7 @@ interface ChatMessage { } interface DeploymentContext { - provider?: 'azure' | 'netlify' | 'replit'; + provider?: 'azure' | 'aws' | 'replit'; resourceType?: string; userQuery: string; errorLogs?: string; @@ -47,7 +47,7 @@ export class AIChatService { this.systemPrompt = `You are an expert cloud infrastructure and DevOps assistant for Instantiate.dev, a multi-cloud deployment platform. Your role is to help users with: 1. Infrastructure planning and architecture recommendations -2. Troubleshooting deployment issues across Azure, Netlify, and Replit +2. Troubleshooting deployment issues across Azure, AWS, and Replit 3. Generating Infrastructure as Code (Terraform, Pulumi, Docker) 4. Optimizing cloud costs and performance 5. Security best practices and compliance @@ -103,13 +103,13 @@ Response format: } } - async generateInfrastructureCode(prompt: string, provider: 'azure' | 'netlify' | 'replit', codeType: 'terraform' | 'pulumi'): Promise<{ code: string; explanation: string }> { + async generateInfrastructureCode(prompt: string, provider: 'azure' | 'aws' | 'replit', codeType: 'terraform' | 'pulumi'): Promise<{ code: string; explanation: string }> { try { const messages = [ { role: 'system', content: this.systemPrompt }, { role: 'user', - content: `Generate ${codeType} code for ${provider} to: ${prompt}. Provide the code and a brief explanation of what it does.` + content: `Generate ${codeType} code for ${provider} to: ${prompt}. ${provider === 'aws' ? 'Include proper VPC, security groups, and load balancer configuration for secure web applications.' : ''} Provide the code and a brief explanation of what it does.` } ]; @@ -232,4 +232,4 @@ Response format: } const aiChatService = new AIChatService(); -export { aiChatService }; \ No newline at end of file +export { aiChatService }; diff --git a/server/cloud-providers/aws-service.ts b/server/cloud-providers/aws-service.ts index 411ad6a..fba597e 100644 --- a/server/cloud-providers/aws-service.ts +++ b/server/cloud-providers/aws-service.ts @@ -6,7 +6,7 @@ interface AWSDeploymentRequest { code: string; codeType: 'javascript' | 'python' | 'html'; region: string; - service: 'lambda' | 'ec2' | 's3' | 'ecs'; + service: 'lambda' | 'ec2' | 's3' | 'ecs' | 'web-app-with-alb'; environmentVariables?: Record; } @@ -152,7 +152,7 @@ export class AWSService { const functions = await lambda.listFunctions().promise(); functions.Functions?.forEach(func => { - if (func.Tags?.['CreatedBy'] === 'Instantiate') { + if (func.Description?.includes('Instantiate')) { resources.push({ id: func.FunctionArn || '', name: func.FunctionName || '', @@ -247,6 +247,220 @@ export class AWSService { return Buffer.from(codeContent); } + + async deployWebAppWithLoadBalancer(spec: AWSDeploymentRequest): Promise { + if (!this.credentials.accessKeyId) { + throw new Error('AWS credentials not configured. Please set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.'); + } + + const ec2 = new AWS.EC2({ region: spec.region }); + const elbv2 = new AWS.ELBv2({ region: spec.region }); + const deploymentId = `${spec.name}-${Date.now()}`; + + try { + const vpc = await this.createVPC(ec2, deploymentId); + const subnets = await this.createSubnets(ec2, vpc.VpcId, deploymentId); + const securityGroup = await this.createSecurityGroup(ec2, vpc.VpcId, deploymentId); + + const instances = await this.createEC2Instances(ec2, spec, subnets[0].SubnetId, securityGroup.GroupId, deploymentId); + + const loadBalancer = await this.createApplicationLoadBalancer(elbv2, subnets.map(s => s.SubnetId), deploymentId); + + const targetGroup = await this.createTargetGroup(elbv2, vpc.VpcId, deploymentId); + await this.registerTargets(elbv2, targetGroup.TargetGroupArn, instances); + + await this.createListener(elbv2, loadBalancer.LoadBalancerArn, targetGroup.TargetGroupArn); + + return { + id: deploymentId, + name: spec.name, + type: 'web-app-with-alb', + region: spec.region, + status: 'deployed', + url: `http://${loadBalancer.DNSName}`, + loadBalancerArn: loadBalancer.LoadBalancerArn, + instanceIds: instances.map(i => i.InstanceId), + createdAt: new Date().toISOString(), + logs: [`Web application with load balancer deployed successfully`] + }; + } catch (error: any) { + throw new Error(`AWS web app deployment failed: ${error.message}`); + } + } + + private async createVPC(ec2: AWS.EC2, deploymentId: string) { + const vpcResult = await ec2.createVpc({ + CidrBlock: '10.0.0.0/16', + TagSpecifications: [{ + ResourceType: 'vpc', + Tags: [ + { Key: 'Name', Value: `${deploymentId}-vpc` }, + { Key: 'CreatedBy', Value: 'Instantiate' } + ] + }] + }).promise(); + + const igwResult = await ec2.createInternetGateway({ + TagSpecifications: [{ + ResourceType: 'internet-gateway', + Tags: [{ Key: 'Name', Value: `${deploymentId}-igw` }] + }] + }).promise(); + + await ec2.attachInternetGateway({ + VpcId: vpcResult.Vpc.VpcId, + InternetGatewayId: igwResult.InternetGateway.InternetGatewayId + }).promise(); + + const routeTableResult = await ec2.createRouteTable({ + VpcId: vpcResult.Vpc.VpcId, + TagSpecifications: [{ + ResourceType: 'route-table', + Tags: [{ Key: 'Name', Value: `${deploymentId}-rt` }] + }] + }).promise(); + + await ec2.createRoute({ + RouteTableId: routeTableResult.RouteTable.RouteTableId, + DestinationCidrBlock: '0.0.0.0/0', + GatewayId: igwResult.InternetGateway.InternetGatewayId + }).promise(); + + return vpcResult.Vpc; + } + + private async createSubnets(ec2: AWS.EC2, vpcId: string, deploymentId: string) { + const availabilityZones = await ec2.describeAvailabilityZones().promise(); + const azs = availabilityZones.AvailabilityZones.slice(0, 2); + + const subnets = []; + for (let i = 0; i < azs.length; i++) { + const subnetResult = await ec2.createSubnet({ + VpcId: vpcId, + CidrBlock: `10.0.${i + 1}.0/24`, + AvailabilityZone: azs[i].ZoneName, + TagSpecifications: [{ + ResourceType: 'subnet', + Tags: [{ Key: 'Name', Value: `${deploymentId}-subnet-${i + 1}` }] + }] + }).promise(); + + await ec2.modifySubnetAttribute({ + SubnetId: subnetResult.Subnet.SubnetId, + MapPublicIpOnLaunch: { Value: true } + }).promise(); + + subnets.push(subnetResult.Subnet); + } + + return subnets; + } + + private async createSecurityGroup(ec2: AWS.EC2, vpcId: string, deploymentId: string) { + const sgResult = await ec2.createSecurityGroup({ + GroupName: `${deploymentId}-sg`, + Description: 'Security group for web application', + VpcId: vpcId, + TagSpecifications: [{ + ResourceType: 'security-group', + Tags: [{ Key: 'Name', Value: `${deploymentId}-sg` }] + }] + }).promise(); + + await ec2.authorizeSecurityGroupIngress({ + GroupId: sgResult.GroupId, + IpPermissions: [ + { + IpProtocol: 'tcp', + FromPort: 80, + ToPort: 80, + IpRanges: [{ CidrIp: '0.0.0.0/0' }] + }, + { + IpProtocol: 'tcp', + FromPort: 22, + ToPort: 22, + IpRanges: [{ CidrIp: '0.0.0.0/0' }] + } + ] + }).promise(); + + return sgResult; + } + + private async createEC2Instances(ec2: AWS.EC2, spec: AWSDeploymentRequest, subnetId: string, securityGroupId: string, deploymentId: string) { + const userData = Buffer.from(`#!/bin/bash +yum update -y +yum install -y httpd +systemctl start httpd +systemctl enable httpd +echo '${spec.code}' > /var/www/html/index.html +`).toString('base64'); + + const instanceResult = await ec2.runInstances({ + ImageId: 'ami-0c02fb55956c7d316', + InstanceType: 't2.micro', + MinCount: 2, + MaxCount: 2, + SecurityGroupIds: [securityGroupId], + SubnetId: subnetId, + UserData: userData, + TagSpecifications: [{ + ResourceType: 'instance', + Tags: [ + { Key: 'Name', Value: `${deploymentId}-instance` }, + { Key: 'CreatedBy', Value: 'Instantiate' } + ] + }] + }).promise(); + + return instanceResult.Instances; + } + + private async createApplicationLoadBalancer(elbv2: AWS.ELBv2, subnetIds: string[], deploymentId: string) { + const albResult = await elbv2.createLoadBalancer({ + Name: `${deploymentId}-alb`.substring(0, 32), + Subnets: subnetIds, + Tags: [ + { Key: 'Name', Value: `${deploymentId}-alb` }, + { Key: 'CreatedBy', Value: 'Instantiate' } + ] + }).promise(); + + return albResult.LoadBalancers[0]; + } + + private async createTargetGroup(elbv2: AWS.ELBv2, vpcId: string, deploymentId: string) { + const tgResult = await elbv2.createTargetGroup({ + Name: `${deploymentId}-tg`.substring(0, 32), + Protocol: 'HTTP', + Port: 80, + VpcId: vpcId, + HealthCheckPath: '/', + Tags: [{ Key: 'CreatedBy', Value: 'Instantiate' }] + }).promise(); + + return tgResult.TargetGroups[0]; + } + + private async registerTargets(elbv2: AWS.ELBv2, targetGroupArn: string, instances: AWS.EC2.Instance[]) { + await elbv2.registerTargets({ + TargetGroupArn: targetGroupArn, + Targets: instances.map(instance => ({ Id: instance.InstanceId, Port: 80 })) + }).promise(); + } + + private async createListener(elbv2: AWS.ELBv2, loadBalancerArn: string, targetGroupArn: string) { + await elbv2.createListener({ + LoadBalancerArn: loadBalancerArn, + Protocol: 'HTTP', + Port: 80, + DefaultActions: [{ + Type: 'forward', + TargetGroupArn: targetGroupArn + }] + }).promise(); + } } -export const awsService = new AWSService(); \ No newline at end of file +export const awsService = new AWSService(); diff --git a/server/cloud-providers/multi-cloud-manager.ts b/server/cloud-providers/multi-cloud-manager.ts index 2d3f672..fe6721b 100644 --- a/server/cloud-providers/multi-cloud-manager.ts +++ b/server/cloud-providers/multi-cloud-manager.ts @@ -8,7 +8,6 @@ import { linodeService } from './linode-service'; import { huaweiCloudService } from './huawei-service'; import { tencentCloudService } from './tencent-service'; import { getAzureService } from '../azure-service'; -import { netlifyDeploymentService } from '../netlify-deployment-service'; interface UnifiedDeploymentRequest { name: string; @@ -30,8 +29,7 @@ type CloudProvider = | 'digitalocean' | 'linode' | 'huawei' - | 'tencent' - | 'netlify'; + | 'tencent'; interface CloudResource { id: string; @@ -75,7 +73,7 @@ export class MultiCloudManager { linode: linodeService, huawei: huaweiCloudService, tencent: tencentCloudService, - netlify: netlifyDeploymentService + }; private resourceCache = new Map(); @@ -179,13 +177,7 @@ export class MultiCloudManager { } break; - case 'netlify': - result = await provider.deployCode({ - name: request.name, - code: request.code, - codeType: request.codeType - }); - break; + default: throw new Error(`Service ${request.service} not supported for provider ${request.provider}`); @@ -307,7 +299,7 @@ export class MultiCloudManager { const providerDistribution: Record = { aws: 0, gcp: 0, azure: 0, alibaba: 0, ibm: 0, oracle: 0, digitalocean: 0, linode: 0, huawei: 0, - tencent: 0, netlify: 0 + tencent: 0 }; const statusDistribution: Record = {}; @@ -381,8 +373,7 @@ export class MultiCloudManager { digitalocean: ['droplet', 'app-platform', 'kubernetes', 'functions'], linode: ['linode', 'kubernetes', 'object-storage', 'nodebalancer'], huawei: ['function-graph', 'ecs', 'obs', 'cce'], - tencent: ['scf', 'cvm', 'cos', 'tke'], - netlify: ['static-sites', 'functions', 'edge-functions'] + tencent: ['scf', 'cvm', 'cos', 'tke'] }; return capabilities[provider] || []; @@ -399,8 +390,7 @@ export class MultiCloudManager { digitalocean: ['nyc1', 'nyc3', 'ams3', 'sgp1', 'lon1', 'fra1'], linode: ['us-east', 'us-west', 'eu-west', 'ap-south'], huawei: ['cn-north-4', 'cn-north-1', 'cn-east-2', 'cn-south-1'], - tencent: ['ap-guangzhou', 'ap-shanghai', 'ap-beijing', 'ap-singapore'], - netlify: ['global'] + tencent: ['ap-guangzhou', 'ap-shanghai', 'ap-beijing', 'ap-singapore'] }; return regions[provider] || []; @@ -424,4 +414,4 @@ export class MultiCloudManager { } } -export const multiCloudManager = new MultiCloudManager(); \ No newline at end of file +export const multiCloudManager = new MultiCloudManager(); diff --git a/server/deployment-service.ts b/server/deployment-service.ts index 2d034d2..19cb837 100644 --- a/server/deployment-service.ts +++ b/server/deployment-service.ts @@ -145,6 +145,33 @@ export class DeploymentService { } else { throw new Error(`Unsupported Azure resource type: ${request.resourceType}`); } + } else if (request.provider === 'aws') { + const { awsService } = await import('./cloud-providers/aws-service'); + + const deploymentSpec = { + name: `deployment-${Date.now()}`, + code: request.code, + codeType: 'html' as const, + region: 'us-east-1', + service: 'web-app-with-alb' as const, + environmentVariables: {} + }; + + const awsResult = await awsService.deployWebAppWithLoadBalancer(deploymentSpec); + + this.addLog(deploymentId, `AWS deployment completed: ${awsResult.id}`); + this.updateDeploymentStatus(deploymentId, 'success'); + + const deployment = this.deployments.get(deploymentId); + if (deployment) { + deployment.outputs = { + deploymentId: awsResult.id, + url: awsResult.url, + loadBalancerArn: awsResult.loadBalancerArn, + instanceIds: awsResult.instanceIds, + region: awsResult.region + }; + } } else { throw new Error(`Unsupported cloud provider: ${request.provider}`); } @@ -402,4 +429,4 @@ subscription_id = "${azureConfig.subscriptionId}"`; } const deploymentService = new DeploymentService(); -export { deploymentService }; \ No newline at end of file +export { deploymentService }; diff --git a/server/deployment-status-manager.ts b/server/deployment-status-manager.ts index 90bcbf8..0b3bcbe 100644 --- a/server/deployment-status-manager.ts +++ b/server/deployment-status-manager.ts @@ -1,6 +1,6 @@ interface DeploymentRecord { id: string; - provider: 'netlify' | 'azure' | 'replit'; + provider: 'azure' | 'replit'; status: 'uploading' | 'processing' | 'ready' | 'error' | 'deployed'; url?: string; createdAt: string; @@ -68,13 +68,6 @@ const deploymentStatusManager = new DeploymentStatusManager(); export { deploymentStatusManager }; // Resolve the specific deployment ID 1749273424917 -deploymentStatusManager.recordDeployment({ - id: '1749273424917', - provider: 'netlify', - status: 'deployed', - url: 'https://deployment-1749273424917-resolved.netlify.app', - createdAt: '2025-06-07T05:17:06.179Z', - updatedAt: new Date().toISOString(), - siteId: '25650649-1b7f-4b9e-9334-cf57728c1139', + deployId: '6843cb5210b36e90784c69fe' -}); \ No newline at end of file +}); diff --git a/server/namecheap/namecheap-service.ts b/server/namecheap/namecheap-service.ts deleted file mode 100644 index 1f2e91b..0000000 --- a/server/namecheap/namecheap-service.ts +++ /dev/null @@ -1,266 +0,0 @@ -import fetch from 'node-fetch'; -import { parseString } from 'xml2js'; -import { promisify } from 'util'; - -const parseXML = promisify(parseString); - -export interface NamecheapDomain { - id: string; - name: string; - user: string; - created: string; - expires: string; - isExpired: boolean; - isLocked: boolean; - autoRenew: boolean; - whoisGuard: string; - isPremium: boolean; - isOurDNS: boolean; -} - -export interface DNSRecord { - type: 'A' | 'AAAA' | 'CNAME' | 'MX' | 'TXT' | 'NS' | 'SRV'; - hostname: string; - address: string; - ttl: number; - mxpref?: number; - recordId?: string; -} - -export interface DomainAvailability { - domain: string; - available: boolean; - premium: boolean; - price?: string; -} - -export class NamecheapService { - private apiUser: string; - private apiKey: string; - private username: string; - private baseUrl = 'https://api.namecheap.com/xml.response'; - private clientIp: string; - - constructor() { - this.apiUser = process.env.NAMECHEAP_API_USER || ''; - this.apiKey = process.env.NAMECHEAP_API_KEY || ''; - this.username = process.env.NAMECHEAP_USERNAME || ''; - this.clientIp = '127.0.0.1'; - } - - private async makeRequest(command: string, params: Record = {}): Promise { - const baseParams = { - ApiUser: this.apiUser, - ApiKey: this.apiKey, - UserName: this.username, - Command: command, - ClientIp: this.clientIp - }; - - const allParams = { ...baseParams, ...params }; - const queryString = new URLSearchParams(allParams).toString(); - const url = `${this.baseUrl}?${queryString}`; - - try { - const response = await fetch(url); - const xmlText = await response.text(); - const result = await parseXML(xmlText); - - if (result.ApiResponse.$.Status === 'ERROR') { - const errors = result.ApiResponse.Errors[0].Error; - const errorMessage = Array.isArray(errors) ? errors[0]._ : errors._; - throw new Error(`Namecheap API Error: ${errorMessage}`); - } - - return result.ApiResponse.CommandResponse[0]; - } catch (error: any) { - throw new Error(`Namecheap API request failed: ${error.message}`); - } - } - - async testConnection(): Promise { - try { - await this.makeRequest('namecheap.domains.getList'); - return true; - } catch (error) { - return false; - } - } - - async getDomains(): Promise { - try { - const response = await this.makeRequest('namecheap.domains.getList'); - const domains = response.DomainGetListResult[0].Domain || []; - - return domains.map((domain: any) => ({ - id: domain.$.ID, - name: domain.$.Name, - user: domain.$.User, - created: domain.$.Created, - expires: domain.$.Expires, - isExpired: domain.$.IsExpired === 'true', - isLocked: domain.$.IsLocked === 'true', - autoRenew: domain.$.AutoRenew === 'true', - whoisGuard: domain.$.WhoisGuard, - isPremium: domain.$.IsPremium === 'true', - isOurDNS: domain.$.IsOurDNS === 'true' - })); - } catch (error: any) { - throw new Error(`Failed to fetch domains: ${error.message}`); - } - } - - async checkDomainAvailability(domains: string[]): Promise { - try { - const domainList = domains.join(','); - const response = await this.makeRequest('namecheap.domains.check', { - DomainList: domainList - }); - - const domainResults = response.DomainCheckResult || []; - return domainResults.map((result: any) => ({ - domain: result.$.Domain, - available: result.$.Available === 'true', - premium: result.$.IsPremiumName === 'true', - price: result.$.PremiumRegistrationPrice - })); - } catch (error: any) { - throw new Error(`Failed to check domain availability: ${error.message}`); - } - } - - async getDNSRecords(domain: string): Promise { - try { - const sld = domain.split('.')[0]; - const tld = domain.split('.').slice(1).join('.'); - - const response = await this.makeRequest('namecheap.domains.dns.getHosts', { - SLD: sld, - TLD: tld - }); - - const hosts = response.DomainDNSGetHostsResult[0].host || []; - return hosts.map((host: any) => ({ - type: host.$.Type, - hostname: host.$.Name, - address: host.$.Address, - ttl: parseInt(host.$.TTL), - mxpref: host.$.MXPref ? parseInt(host.$.MXPref) : undefined, - recordId: host.$.HostId - })); - } catch (error: any) { - throw new Error(`Failed to fetch DNS records for ${domain}: ${error.message}`); - } - } - - async setDNSRecords(domain: string, records: DNSRecord[]): Promise { - try { - const sld = domain.split('.')[0]; - const tld = domain.split('.').slice(1).join('.'); - - const params: Record = { - SLD: sld, - TLD: tld - }; - - records.forEach((record, index) => { - const i = index + 1; - params[`HostName${i}`] = record.hostname; - params[`RecordType${i}`] = record.type; - params[`Address${i}`] = record.address; - params[`TTL${i}`] = record.ttl.toString(); - if (record.mxpref) { - params[`MXPref${i}`] = record.mxpref.toString(); - } - }); - - await this.makeRequest('namecheap.domains.dns.setHosts', params); - return true; - } catch (error: any) { - throw new Error(`Failed to set DNS records for ${domain}: ${error.message}`); - } - } - - async setupCloudflareIntegration(domain: string): Promise { - try { - const sld = domain.split('.')[0]; - const tld = domain.split('.').slice(1).join('.'); - - await this.makeRequest('namecheap.domains.dns.setCustom', { - SLD: sld, - TLD: tld, - Nameservers: 'ns1.cloudflare.com,ns2.cloudflare.com' - }); - - return true; - } catch (error: any) { - throw new Error(`Failed to setup Cloudflare for ${domain}: ${error.message}`); - } - } - - async renewDomain(domain: string, years: number = 1): Promise { - try { - const sld = domain.split('.')[0]; - const tld = domain.split('.').slice(1).join('.'); - - await this.makeRequest('namecheap.domains.renew', { - DomainName: `${sld}.${tld}`, - Years: years.toString() - }); - - return true; - } catch (error: any) { - throw new Error(`Failed to renew domain ${domain}: ${error.message}`); - } - } - - async enableAutoRenew(domain: string): Promise { - try { - const sld = domain.split('.')[0]; - const tld = domain.split('.').slice(1).join('.'); - - await this.makeRequest('namecheap.domains.setRenewalMode', { - DomainName: `${sld}.${tld}`, - RenewalMode: 'auto' - }); - - return true; - } catch (error: any) { - throw new Error(`Failed to enable auto-renew for ${domain}: ${error.message}`); - } - } - - async getSSLCertificates(): Promise { - try { - const response = await this.makeRequest('namecheap.ssl.getList'); - return response.SSLListResult[0].SSL || []; - } catch (error: any) { - throw new Error(`Failed to fetch SSL certificates: ${error.message}`); - } - } - - async updateClientIP(ip: string): Promise { - this.clientIp = ip; - } - - async getExternalIP(): Promise { - try { - const response = await fetch('https://api.ipify.org?format=json'); - const data = await response.json() as { ip: string }; - return data.ip; - } catch (error) { - return '127.0.0.1'; - } - } - - async initializeService(): Promise { - try { - const externalIP = await this.getExternalIP(); - await this.updateClientIP(externalIP); - } catch (error) { - console.warn('Failed to get external IP, using localhost'); - } - } -} - -export const namecheapService = new NamecheapService(); \ No newline at end of file diff --git a/server/routes.ts b/server/routes.ts index e4c3879..2fafac8 100644 --- a/server/routes.ts +++ b/server/routes.ts @@ -1848,110 +1848,57 @@ export async function registerRoutes(app: Express): Promise { } }); - // Netlify deployment routes - app.post("/api/real-deploy/netlify", async (req, res) => { + // AWS deployment endpoint + app.post("/api/real-deploy/aws", async (req, res) => { try { - const { netlifyDeploymentService } = await import('./netlify-deployment-service'); - const { name, htmlContent, environmentVariables } = req.body; + const { awsService } = await import('./cloud-providers/aws-service'); + const { name, code, codeType, region, service, environmentVariables } = req.body; - if (!name) { + if (!name || !code) { return res.status(400).json({ success: false, - error: "Missing required parameter: name" + error: "Missing required parameters: name, code" }); } - const result = await netlifyDeploymentService.deployCode({ + const deploymentSpec = { name, - code: htmlContent || ` - - - - ${name} - - - -
-

Deployment Successful

-
- Application "${name}" deployed successfully via Instanti8 Platform -
-

Deployment timestamp: ${new Date().toISOString()}

-
- -`, - codeType: 'html' as const - }); + code: code || `

Hello from ${name}

Deployed via Instantiate

`, + codeType: codeType || 'html', + region: region || 'us-east-1', + service: service || 'web-app-with-alb', + environmentVariables: environmentVariables || {} + }; + + let result; + if (deploymentSpec.service === 'web-app-with-alb') { + result = await awsService.deployWebAppWithLoadBalancer(deploymentSpec); + } else if (deploymentSpec.service === 'lambda') { + result = await awsService.deployLambda(deploymentSpec); + } else if (deploymentSpec.service === 's3') { + result = await awsService.deployS3Website(deploymentSpec); + } else { + throw new Error(`Unsupported AWS service: ${deploymentSpec.service}`); + } res.json({ - success: result.success, - siteId: result.siteId, - deployId: result.deployId, + success: result.id ? true : false, + deploymentId: result.id, + name: result.name, + type: result.type, + region: result.region, + status: result.status, url: result.url, - adminUrl: result.adminUrl, - buildStatus: result.buildStatus, + loadBalancerArn: result.loadBalancerArn, + instanceIds: result.instanceIds, error: result.error, - message: result.success ? "Netlify deployment completed successfully" : "Netlify deployment failed" + message: result.id ? "AWS deployment completed successfully" : "AWS deployment failed" }); } catch (error: any) { res.status(500).json({ success: false, - error: "Netlify deployment failed", - message: error.message - }); - } - }); - - app.get("/api/netlify/sites", async (req, res) => { - try { - const { netlifyDeploymentService } = await import('./netlify-deployment-service'); - const sites = await netlifyDeploymentService.listSites(); - - res.json({ - success: true, - sites: sites.map(site => ({ - id: site.id, - name: site.name, - url: site.url, - adminUrl: site.admin_url, - createdAt: site.created_at, - updatedAt: site.updated_at - })) - }); - - } catch (error: any) { - res.status(500).json({ - success: false, - error: "Failed to list Netlify sites", - message: error.message - }); - } - }); - - app.get("/api/netlify/deploy/:deployId/status", async (req, res) => { - try { - const { netlifyDeploymentService } = await import('./netlify-deployment-service'); - const { deployId } = req.params; - - const status = await netlifyDeploymentService.getDeploymentStatus(deployId, 'deploy'); - - res.json({ - success: true, - deployId, - status: status || 'unknown', - url: '', - errorMessage: '' - }); - - } catch (error: any) { - res.status(500).json({ - success: false, - error: "Failed to get deployment status", + error: "AWS deployment failed", message: error.message }); } @@ -2310,7 +2257,7 @@ const files = ${JSON.stringify(result.files, null, 2)};`, // Use AI for general deployment assistance const originalProvider = codeGenerator.determineProvider(message); - const validProvider = originalProvider === 'aws' || originalProvider === 'gcp' ? 'azure' : originalProvider as 'azure' | 'netlify' | 'replit'; + const validProvider = originalProvider as 'azure' | 'aws' | 'netlify' | 'replit'; const deploymentContext = { userQuery: message, diff --git a/server/routes/cleanup-resources.ts b/server/routes/cleanup-resources.ts deleted file mode 100644 index 24bb3e1..0000000 --- a/server/routes/cleanup-resources.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { Router } from 'express'; -import { netlifyDeploymentService } from '../netlify-deployment-service'; - -const router = Router(); - -// Clean up old/unused deployments -router.delete('/cleanup/netlify', async (req, res) => { - try { - const deployments = await netlifyDeploymentService.listDeployments(); - const toDelete = deployments.filter(d => - d.name.includes('netlify-app-') || - d.name.includes('deployment-') || - d.name.includes('instantiate-') || - d.name === 'afroconnectng' || - d.name === 'instat8' - ); - - const results = []; - for (const deployment of toDelete) { - try { - await netlifyDeploymentService.deleteDeployment(deployment.id); - results.push({ id: deployment.id, name: deployment.name, status: 'deleted' }); - } catch (error) { - results.push({ id: deployment.id, name: deployment.name, status: 'failed', error: error.message }); - } - } - - res.json({ - success: true, - message: `Cleaned up ${results.filter(r => r.status === 'deleted').length} deployments`, - results - }); - } catch (error) { - res.status(500).json({ - success: false, - error: error.message - }); - } -}); - -// Remove all old deployments -router.delete('/cleanup/all', async (req, res) => { - try { - const deployments = await netlifyDeploymentService.listDeployments(); - const results = []; - - for (const deployment of deployments) { - try { - await netlifyDeploymentService.deleteDeployment(deployment.id); - results.push({ id: deployment.id, name: deployment.name, status: 'deleted' }); - } catch (error) { - results.push({ id: deployment.id, name: deployment.name, status: 'failed', error: error.message }); - } - } - - res.json({ - success: true, - message: `Cleaned up ${results.filter(r => r.status === 'deleted').length} deployments`, - results - }); - } catch (error) { - res.status(500).json({ - success: false, - error: error.message - }); - } -}); - -export { router as cleanupRoutes }; \ No newline at end of file diff --git a/src/components/dashboard/cloud-architecture-diagram.tsx b/src/components/dashboard/cloud-architecture-diagram.tsx index 9163b34..8c406d3 100644 --- a/src/components/dashboard/cloud-architecture-diagram.tsx +++ b/src/components/dashboard/cloud-architecture-diagram.tsx @@ -55,7 +55,7 @@ export function CloudArchitectureDiagram() { { name: 'Alibaba', label: 'é˜ŋ里' }, { name: 'Huawei', label: 'HW' }, { name: 'Tencent', label: 'č…ūčŪŊ' }, - { name: 'Netlify', label: 'NET' } + ]; return ( @@ -306,4 +306,4 @@ export function CloudArchitectureDiagram() { ); -} \ No newline at end of file +} diff --git a/src/components/dashboard/cloud-insights-dashboard.tsx b/src/components/dashboard/cloud-insights-dashboard.tsx index 2f92863..7d50cc9 100644 --- a/src/components/dashboard/cloud-insights-dashboard.tsx +++ b/src/components/dashboard/cloud-insights-dashboard.tsx @@ -38,7 +38,7 @@ export function CloudInsightsDashboard() { aws: , azure: , gcp: , - netlify: , + digitalocean: , linode: , default: @@ -134,7 +134,7 @@ export function CloudInsightsDashboard() {
- {['AWS', 'Azure', 'Google Cloud', 'Netlify', 'DigitalOcean', 'Linode', 'Alibaba Cloud', 'IBM Cloud', 'Oracle Cloud', 'Huawei Cloud', 'Tencent Cloud'].map((provider, index) => ( + {['AWS', 'Azure', 'Google Cloud', 'DigitalOcean', 'Linode', 'Alibaba Cloud', 'IBM Cloud', 'Oracle Cloud', 'Huawei Cloud', 'Tencent Cloud'].map((provider, index) => (
@@ -267,4 +267,4 @@ export function CloudInsightsDashboard() {
); -} \ No newline at end of file +} diff --git a/src/components/dashboard/multi-cloud-overview.tsx b/src/components/dashboard/multi-cloud-overview.tsx index a79cd7d..2ca716f 100644 --- a/src/components/dashboard/multi-cloud-overview.tsx +++ b/src/components/dashboard/multi-cloud-overview.tsx @@ -64,7 +64,7 @@ const providerIcons: Record = { linode: Server, huawei: Cloud, tencent: Cloud, - netlify: Globe + }; const providerNames: Record = { @@ -78,7 +78,7 @@ const providerNames: Record = { linode: 'Linode', huawei: 'Huawei Cloud', tencent: 'Tencent Cloud', - netlify: 'Netlify' + }; const statusColors: Record = { @@ -503,4 +503,4 @@ export function MultiCloudOverview() {
); -} \ No newline at end of file +} diff --git a/src/components/dashboard/sidebar.tsx b/src/components/dashboard/sidebar.tsx index e6ad5db..1cfae17 100644 --- a/src/components/dashboard/sidebar.tsx +++ b/src/components/dashboard/sidebar.tsx @@ -13,10 +13,10 @@ export function Sidebar({ currentSection, onSectionChange }: SidebarProps) { { id: "projects", label: "Projects", icon: Folder, badge: "3" }, { id: "deployments", label: "Deployments", icon: Rocket, badge: "2" }, { id: "azure-docker", label: "Azure Docker", icon: Cloud }, - { id: "multi-cloud", label: "Multi-Cloud", icon: Globe, badge: "11" }, + { id: "multi-cloud", label: "Multi-Cloud", icon: Globe, badge: "9" }, { id: "infrastructure", label: "Import Infrastructure", icon: Server }, { id: "import-wizard", label: "Import Wizard", icon: Activity }, - { id: "domains", label: "Domain Manager", icon: Globe }, + { id: "monitoring", label: "Monitoring", icon: BarChart3 }, ]; diff --git a/src/components/domains/domain-manager.tsx b/src/components/domains/domain-manager.tsx deleted file mode 100644 index 4bbca03..0000000 --- a/src/components/domains/domain-manager.tsx +++ /dev/null @@ -1,382 +0,0 @@ -import { useState } from "react"; -import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; -import { Button } from "@/components/ui/button"; -import { Badge } from "@/components/ui/badge"; -import { Input } from "@/components/ui/input"; -import { Label } from "@/components/ui/label"; -import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; -import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; -import { - Globe, - Plus, - Search, - Settings, - Shield, - RefreshCw, - Calendar, - Lock, - Unlock, - Zap, - CheckCircle, - AlertTriangle -} from "lucide-react"; - -interface Domain { - id: string; - name: string; - created: string; - expires: string; - isExpired: boolean; - isLocked: boolean; - autoRenew: boolean; - whoisGuard: string; - isPremium: boolean; - isOurDNS: boolean; -} - -interface DNSRecord { - type: string; - hostname: string; - address: string; - ttl: number; - recordId?: string; -} - -export function DomainManager() { - const [selectedDomain, setSelectedDomain] = useState(""); - const [searchQuery, setSearchQuery] = useState(""); - const [newRecord, setNewRecord] = useState({ - type: 'A', - hostname: '', - address: '', - ttl: 300 - }); - - const queryClient = useQueryClient(); - - const { data: domains, isLoading: domainsLoading } = useQuery({ - queryKey: ['/api/namecheap/domains'], - staleTime: 1000 * 60 * 5, - }); - - const { data: dnsRecords, isLoading: dnsLoading } = useQuery({ - queryKey: ['/api/namecheap/dns', selectedDomain], - enabled: !!selectedDomain, - staleTime: 1000 * 60 * 2, - }); - - const { data: availability } = useQuery({ - queryKey: ['/api/namecheap/check', searchQuery], - enabled: searchQuery.length > 3 && searchQuery.includes('.'), - staleTime: 1000 * 60 * 5, - }); - - const getDomainStatus = (domain: Domain) => { - if (domain.isExpired) { - return Expired; - } - - const expiryDate = new Date(domain.expires); - const daysToExpiry = Math.ceil((expiryDate.getTime() - new Date().getTime()) / (1000 * 60 * 60 * 24)); - - if (daysToExpiry <= 30) { - return Expires in {daysToExpiry} days; - } - - return Active; - }; - - if (domainsLoading) { - return ( -
-
-
- ); - } - - return ( -
-
-
-

Domain Manager

-

Manage your Namecheap domains and DNS settings

-
-
- - Namecheap Connected - -
-
- - - - My Domains ({(domains as any)?.length || 0}) - DNS Management - Domain Search - SSL Certificates - - - - - - Your Domains - - Manage your registered domains - - - -
- {((domains as any) || []).map((domain: Domain) => ( -
-
- -
-

{domain.name}

-
- - Expires: {new Date(domain.expires).toLocaleDateString()} - {domain.isLocked ? : } - {domain.autoRenew && } -
-
-
-
- {getDomainStatus(domain)} -
- - -
-
-
- ))} - - {(!domains || (domains as any).length === 0) && ( -
- -

No domains found in your Namecheap account.

-
- )} -
-
-
-
- - -
- - - Select Domain - - - - - {selectedDomain && ( -
-

Add DNS Record

-
-
- - -
-
- - setNewRecord(prev => ({ ...prev, hostname: e.target.value }))} - placeholder="@ or subdomain" - className="bg-blue-900 border-blue-700 text-white" - /> -
-
- - setNewRecord(prev => ({ ...prev, address: e.target.value }))} - placeholder="IP address or value" - className="bg-blue-900 border-blue-700 text-white" - /> -
-
- - setNewRecord(prev => ({ ...prev, ttl: parseInt(e.target.value) }))} - className="bg-blue-900 border-blue-700 text-white" - /> -
- -
-
- )} -
-
- -
- - - DNS Records - - {selectedDomain ? `DNS records for ${selectedDomain}` : 'Select a domain to view DNS records'} - - - - {selectedDomain ? ( - dnsLoading ? ( -
-
-
- ) : ( - - - - Type - Hostname - Value - TTL - - - - {((dnsRecords as any) || []).map((record: DNSRecord, index: number) => ( - - - {record.type} - - {record.hostname} - {record.address} - {record.ttl} - - ))} - -
- ) - ) : ( -
- -

Select a domain to manage DNS records

-
- )} -
-
-
-
-
- - - - - Domain Search - - Search for available domains - - - -
-
- setSearchQuery(e.target.value)} - placeholder="Enter domain name (e.g., mysite.com)" - className="bg-blue-900 border-blue-700 text-white" - /> - -
- - {availability && ( -
- {(availability as any).map((domain: any, index: number) => ( -
-
- - {domain.domain} - {domain.premium && Premium} -
-
- {domain.available ? ( - <> - Available - - - ) : ( - Taken - )} -
-
- ))} -
- )} -
-
-
-
- - - - - SSL Certificates - - Manage SSL certificates for your domains - - - -
- -

SSL certificate management

-

Automatically provision SSL certificates for your domains

-
-
-
-
-
-
- ); -} \ No newline at end of file diff --git a/src/components/layout/footer.tsx b/src/components/layout/footer.tsx index fe811f4..e8dac82 100644 --- a/src/components/layout/footer.tsx +++ b/src/components/layout/footer.tsx @@ -34,14 +34,7 @@ export function Footer() { > - - - +
@@ -82,7 +75,7 @@ export function Footer() {
  • Linode
  • Huawei Cloud
  • Tencent Cloud
  • -
  • Netlify
  • + @@ -127,4 +120,4 @@ export function Footer() { ); -} \ No newline at end of file +} diff --git a/src/pages/dashboard.tsx b/src/pages/dashboard.tsx index 8ce68c8..d2d8492 100644 --- a/src/pages/dashboard.tsx +++ b/src/pages/dashboard.tsx @@ -12,13 +12,13 @@ import { MultiCloudOverview } from "@/components/dashboard/multi-cloud-overview" import { CloudInsightsDashboard } from "@/components/dashboard/cloud-insights-dashboard"; import { InfrastructureImporter } from "@/components/infrastructure/infrastructure-importer"; import { ImportWizard } from "@/components/infrastructure/import-wizard"; -import { DomainManager } from "@/components/domains/domain-manager"; + import { ChatPanel } from "@/components/chat/chat-panel"; import { Button } from "@/components/ui/button"; import { Footer } from "@/components/layout/footer"; import { Plus } from "lucide-react"; -type Section = "overview" | "projects" | "deployments" | "azure-docker" | "multi-cloud" | "infrastructure" | "import-wizard" | "domains" | "monitoring" | "settings"; +type Section = "overview" | "projects" | "deployments" | "azure-docker" | "multi-cloud" | "infrastructure" | "import-wizard" | "monitoring" | "settings"; const sectionTitles: Record = { overview: { title: "Overview", subtitle: "Monitor your deployments and infrastructure" }, @@ -28,7 +28,7 @@ const sectionTitles: Record = { "multi-cloud": { title: "Multi-Cloud", subtitle: "Unified dashboard for all cloud providers" }, infrastructure: { title: "Infrastructure", subtitle: "Import existing infrastructure from any cloud provider" }, "import-wizard": { title: "Import Wizard", subtitle: "Step-by-step infrastructure import and conversion" }, - domains: { title: "Domain Manager", subtitle: "Manage your Namecheap domains and DNS settings" }, + monitoring: { title: "Monitoring", subtitle: "Real-time metrics and alerts" }, settings: { title: "Settings", subtitle: "Configure environment variables and cloud credentials" }, }; @@ -48,8 +48,7 @@ export default function Dashboard() { return ; case "import-wizard": return ; - case "domains": - return ; + case "monitoring": return ; case "azure-docker": diff --git a/src/pages/landing.tsx b/src/pages/landing.tsx index bda5d1a..3cb4a88 100644 --- a/src/pages/landing.tsx +++ b/src/pages/landing.tsx @@ -13,8 +13,8 @@ export function Landing() {
    ☁ïļ
    -

    11 Cloud Providers

    -

    AWS, Azure, GCP, Alibaba, IBM, Oracle, DigitalOcean, Linode, Huawei, Tencent, Netlify

    +

    9 Cloud Providers

    +

    AWS, Azure, GCP, Alibaba, IBM, Oracle, DigitalOcean, Linode, Huawei, Tencent

    📊
    diff --git a/src/pages/pricing.tsx b/src/pages/pricing.tsx index c631341..00e65f7 100644 --- a/src/pages/pricing.tsx +++ b/src/pages/pricing.tsx @@ -25,7 +25,7 @@ export function Pricing() { period: "per month", description: "For growing teams", features: [ - "All 11 cloud providers", + "All 9 cloud providers", "Advanced analytics", "Priority support", "Unlimited deployments",