UNPKG

@aerocorp/cli

Version:

AeroCorp CLI 5.1.0 - Future-Proofed Enterprise Infrastructure with Live Preview, Tunneling & Advanced DevOps

295 lines • 13 kB
"use strict"; /** * AeroCorp CLI 5.0.0 - Vercel-like Deployment Service * Windows-native deployment that works like "npx vercel --prod" * Uses HTTP APIs primarily, SSH only as fallback */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.VercelLikeDeployService = void 0; const chalk_1 = __importDefault(require("chalk")); const ora_1 = __importDefault(require("ora")); const fs_1 = require("fs"); const config_1 = require("./config"); const coolify_1 = require("./coolify"); const ssh_native_1 = require("./ssh-native"); const windows_native_1 = require("./windows-native"); class VercelLikeDeployService { constructor() { this.configService = new config_1.ConfigService(); this.coolifyService = new coolify_1.CoolifyService(); this.sshService = new ssh_native_1.NativeSSHService(); this.windowsService = new windows_native_1.WindowsNativeService(); } /** * Main deployment function - works like "npx vercel --prod" */ async deploy(options = {}) { const startTime = Date.now(); console.log(chalk_1.default.cyan.bold('\nšŸš€ AeroCorp Deployment (Vercel-like)')); console.log(chalk_1.default.gray('─'.repeat(50))); try { // Step 1: Environment validation await this.validateEnvironment(); // Step 2: Project detection const project = await this.detectProject(); console.log(chalk_1.default.blue(`šŸ“¦ Detected: ${project.type} project`)); // Step 3: Build if needed if (options.build !== false && project.buildCommand) { await this.buildProject(project); } // Step 4: Deploy via Coolify API (primary method) const deployResult = await this.deployViaCoolify(project, options); const duration = Date.now() - startTime; console.log(chalk_1.default.green.bold('\nšŸŽ‰ Deployment completed successfully!')); console.log(chalk_1.default.white(`ā±ļø Duration: ${Math.round(duration / 1000)}s`)); if (deployResult.url) { console.log(chalk_1.default.blue(`šŸ”— URL: ${deployResult.url}`)); } return { success: true, url: deployResult.url, deploymentId: deployResult.deploymentId, duration }; } catch (error) { const duration = Date.now() - startTime; console.log(chalk_1.default.red.bold('\nāŒ Deployment failed')); console.log(chalk_1.default.white(`ā±ļø Duration: ${Math.round(duration / 1000)}s`)); console.error(chalk_1.default.red('Error:'), error.message); return { success: false, duration }; } } /** * Validate deployment environment */ async validateEnvironment() { const spinner = (0, ora_1.default)('Validating environment...').start(); try { // Check authentication if (!this.coolifyService.isAuthenticated()) { spinner.fail('Authentication required'); console.log(chalk_1.default.red('āŒ Not authenticated with Coolify')); console.log(chalk_1.default.yellow('šŸ’” Run: aerocorp coolify login')); throw new Error('Authentication required'); } // Check Coolify connectivity const healthCheck = await this.coolifyService.healthCheck(); if (!healthCheck) { throw new Error('Coolify health check failed'); } spinner.succeed('Environment validated'); } catch (error) { spinner.fail('Environment validation failed'); throw error; } } /** * Detect project type and configuration */ async detectProject() { const spinner = (0, ora_1.default)('Detecting project type...').start(); try { let type = 'unknown'; let buildCommand; let outputDir; let packageManager = 'npm'; // Check for package manager if ((0, fs_1.existsSync)('pnpm-lock.yaml')) { packageManager = 'pnpm'; } else if ((0, fs_1.existsSync)('yarn.lock')) { packageManager = 'yarn'; } // Check for project type if ((0, fs_1.existsSync)('vite.config.ts') || (0, fs_1.existsSync)('vite.config.js')) { type = 'vite'; buildCommand = `${packageManager} run build`; outputDir = 'dist'; } else if ((0, fs_1.existsSync)('next.config.js') || (0, fs_1.existsSync)('next.config.ts')) { type = 'next'; buildCommand = `${packageManager} run build`; outputDir = '.next'; } else if ((0, fs_1.existsSync)('package.json')) { const pkg = JSON.parse((0, fs_1.readFileSync)('package.json', 'utf8')); if (pkg.dependencies?.react || pkg.devDependencies?.react) { type = 'react'; buildCommand = `${packageManager} run build`; outputDir = 'build'; } else { type = 'node'; buildCommand = pkg.scripts?.build ? `${packageManager} run build` : undefined; } } else if ((0, fs_1.existsSync)('index.html')) { type = 'static'; outputDir = '.'; } const hasDockerfile = (0, fs_1.existsSync)('Dockerfile'); spinner.succeed(`Project detected: ${type}`); return { type, buildCommand, outputDir, packageManager, hasDockerfile }; } catch (error) { spinner.fail('Project detection failed'); throw error; } } /** * Build project using detected package manager */ async buildProject(project) { if (!project.buildCommand) { console.log(chalk_1.default.blue('šŸ“¦ No build command detected, skipping build')); return; } const spinner = (0, ora_1.default)(`Building project with ${project.packageManager}...`).start(); try { const { spawn } = require('child_process'); const [command, ...args] = project.buildCommand.split(' '); const buildProcess = spawn(command, args, { stdio: ['pipe', 'pipe', 'pipe'], shell: true, cwd: process.cwd() }); let buildOutput = ''; let buildError = ''; buildProcess.stdout?.on('data', (data) => { buildOutput += data.toString(); }); buildProcess.stderr?.on('data', (data) => { buildError += data.toString(); }); await new Promise((resolve, reject) => { buildProcess.on('close', (code) => { if (code === 0) { resolve(void 0); } else { reject(new Error(`Build failed with code ${code}\n${buildError}`)); } }); buildProcess.on('error', (error) => { reject(new Error(`Build process error: ${error.message}`)); }); }); spinner.succeed('Project built successfully'); console.log(chalk_1.default.green('āœ… Build completed')); } catch (error) { spinner.fail('Build failed'); throw error; } } /** * Deploy via Coolify API (primary method - like Vercel) */ async deployViaCoolify(project, options) { const spinner = (0, ora_1.default)('Deploying via Coolify API...').start(); try { // Determine environment const environment = options.prod ? 'production' : (options.preview ? 'preview' : 'staging'); spinner.text = `Deploying to ${environment}...`; // Use Coolify service for deployment const deployResult = await this.coolifyService.deploy({ app: options.app, branch: options.branch, tag: options.tag, environment }); spinner.succeed(`Deployed to ${environment}`); return { url: deployResult.url, deploymentId: deployResult.deployment_id }; } catch (error) { spinner.fail('Coolify API deployment failed'); // Fallback to SSH deployment if API fails console.log(chalk_1.default.yellow('šŸ”„ Falling back to SSH deployment...')); return await this.deployViaSSH(project, options); } } /** * Fallback SSH deployment method */ async deployViaSSH(project, options) { const spinner = (0, ora_1.default)('Deploying via SSH fallback...').start(); try { // Connect to server const connected = await this.sshService.connect(); if (!connected) { throw new Error('SSH connection failed'); } // Execute deployment commands via SSH const deployCommands = [ 'cd /opt/coolify', `docker-compose exec coolify php artisan app:deploy ${options.app || 'default'}` ]; for (const command of deployCommands) { spinner.text = `Executing: ${command}`; const result = await this.sshService.executeCommand(command); if (!result.success) { throw new Error(`SSH command failed: ${command}\n${result.error}`); } } spinner.succeed('SSH deployment completed'); return { url: `https://${options.app || 'app'}.aerocorpindustries.org`, deploymentId: `ssh-${Date.now()}` }; } catch (error) { spinner.fail('SSH deployment failed'); throw error; } finally { await this.sshService.disconnect(); } } /** * Show deployment help (Vercel-like) */ showDeploymentHelp() { console.log(chalk_1.default.cyan.bold('\nšŸš€ AeroCorp Deployment Commands')); console.log(chalk_1.default.gray('─'.repeat(50))); console.log(chalk_1.default.white('\nšŸ“‹ Basic Usage:')); console.log(chalk_1.default.blue(' aerocorp deploy # Deploy to staging')); console.log(chalk_1.default.blue(' aerocorp deploy --prod # Deploy to production')); console.log(chalk_1.default.blue(' aerocorp deploy --preview # Deploy preview')); console.log(chalk_1.default.white('\nšŸŽÆ Advanced Options:')); console.log(chalk_1.default.blue(' aerocorp deploy --app <uuid> # Specific application')); console.log(chalk_1.default.blue(' aerocorp deploy --branch <name> # Specific branch')); console.log(chalk_1.default.blue(' aerocorp deploy --tag <version> # Specific tag')); console.log(chalk_1.default.blue(' aerocorp deploy --no-build # Skip build step')); console.log(chalk_1.default.white('\nšŸ”„ PR Previews:')); console.log(chalk_1.default.blue(' aerocorp preview up --pr 123 --app <uuid> --branch <name>')); console.log(chalk_1.default.blue(' aerocorp preview down --pr 123 --app <uuid>')); console.log(chalk_1.default.white('\n🪟 Windows-Specific:')); console.log(chalk_1.default.blue(' aerocorp windows check # Check Windows environment')); console.log(chalk_1.default.blue(' aerocorp windows setup-ssh # Setup SSH (fallback)')); console.log(chalk_1.default.blue(' aerocorp windows test # Test all functionality')); console.log(chalk_1.default.white('\nšŸ’” Pro Tips:')); console.log(chalk_1.default.gray(' • Set COOLIFY_TOKEN environment variable for automation')); console.log(chalk_1.default.gray(' • Use --prod flag for production deployments')); console.log(chalk_1.default.gray(' • SSH is only used as fallback - HTTP API is primary')); console.log(chalk_1.default.gray(' • Works natively on Windows, macOS, and Linux')); } } exports.VercelLikeDeployService = VercelLikeDeployService; //# sourceMappingURL=vercel-like-deploy.js.map