UNPKG

@aerocorp/cli

Version:

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

294 lines (241 loc) β€’ 10.1 kB
/** * AeroCorp CLI 4.0.0 - Enhanced Deployment Service * Advanced deployment management for hybrid infrastructure */ import axios from 'axios'; import chalk from 'chalk'; import inquirer from 'inquirer'; import { ConfigService } from './config'; import { AuthService } from './auth'; export interface Application { uuid: string; name: string; status: 'running' | 'stopped' | 'deploying' | 'failed'; platform: 'coolify' | 'caprover'; url: string; repository: string; branch: string; version: string; lastDeploy: string; environment: string; } export interface DeploymentLog { timestamp: string; level: 'info' | 'warn' | 'error'; message: string; details?: any; } export class DeploymentService { private configService: ConfigService; private authService: AuthService; constructor() { this.configService = new ConfigService(); this.authService = new AuthService(); } async listApplications(options: { platform?: string; status?: string } = {}): Promise<void> { try { const config = await this.configService.getConfig(); const auth = await this.authService.getAuth(); const params = new URLSearchParams(); if (options.platform) params.append('platform', options.platform); if (options.status) params.append('status', options.status); const response = await axios.get(`${config.apiUrl}/api/applications?${params}`, { headers: { 'Authorization': `Bearer ${auth.token}`, 'Content-Type': 'application/json' }, timeout: 10000 }); const data = response.data; console.log(chalk.cyan.bold('\nπŸš€ Applications')); console.log(chalk.gray(`Total: ${data.total} applications`)); console.log(chalk.gray(`Coolify: ${data.platforms.coolify} | CapRover: ${data.platforms.caprover}`)); if (data.applications.length === 0) { console.log(chalk.yellow('No applications found')); return; } console.log('\n' + chalk.white('Name'.padEnd(25) + 'Status'.padEnd(12) + 'Platform'.padEnd(12) + 'Version'.padEnd(12) + 'Last Deploy')); console.log(chalk.gray('─'.repeat(80))); data.applications.forEach((app: Application) => { const statusIcon = app.status === 'running' ? 'βœ…' : app.status === 'deploying' ? 'πŸ”„' : app.status === 'failed' ? '❌' : '⏸️'; const statusColor = app.status === 'running' ? chalk.green : app.status === 'deploying' ? chalk.blue : app.status === 'failed' ? chalk.red : chalk.yellow; console.log( `${statusIcon} ${chalk.white(app.name.padEnd(22))} ` + `${statusColor(app.status.padEnd(11))} ` + `${chalk.cyan(app.platform.padEnd(11))} ` + `${chalk.white(app.version.padEnd(11))} ` + `${chalk.gray(new Date(app.lastDeploy).toLocaleString())}` ); }); } catch (error) { throw new Error(`Failed to list applications: ${error.message}`); } } async deployApplication(uuid: string, options: { branch?: string; environment?: string } = {}): Promise<void> { try { const config = await this.configService.getConfig(); const auth = await this.authService.getAuth(); console.log(chalk.blue('πŸ”„ Starting deployment...')); const response = await axios.post(`${config.apiUrl}/api/applications/${uuid}/deploy`, options, { headers: { 'Authorization': `Bearer ${auth.token}`, 'Content-Type': 'application/json' }, timeout: 30000 }); const deployment = response.data; console.log(chalk.green('βœ… Deployment started successfully!')); console.log(chalk.white(`Deployment ID: ${deployment.deploymentId}`)); console.log(chalk.white(`Application: ${deployment.application.name}`)); console.log(chalk.white(`Estimated time: ${deployment.estimatedTime}`)); // Monitor deployment progress await this.monitorDeployment(uuid, deployment.deploymentId); } catch (error) { throw new Error(`Failed to deploy application: ${error.message}`); } } async createApplication(options: any = {}): Promise<void> { try { let appConfig; if (options.interactive !== false) { appConfig = await inquirer.prompt([ { type: 'input', name: 'name', message: 'Application name:', default: options.name, validate: (input) => input.length > 0 || 'Name is required' }, { type: 'input', name: 'repository', message: 'Repository URL:', default: options.repository, validate: (input) => input.length > 0 || 'Repository is required' }, { type: 'input', name: 'branch', message: 'Branch:', default: options.branch || 'main' }, { type: 'list', name: 'platform', message: 'Deployment platform:', choices: ['coolify', 'caprover'], default: options.platform || 'coolify' }, { type: 'list', name: 'environment', message: 'Environment:', choices: ['production', 'staging', 'development'], default: options.environment || 'production' } ]); } else { appConfig = options; } const config = await this.configService.getConfig(); const auth = await this.authService.getAuth(); console.log(chalk.blue('πŸ”„ Creating application...')); const response = await axios.post(`${config.apiUrl}/api/applications`, appConfig, { headers: { 'Authorization': `Bearer ${auth.token}`, 'Content-Type': 'application/json' }, timeout: 30000 }); const application = response.data.application; console.log(chalk.green('βœ… Application created successfully!')); console.log(chalk.white(`Name: ${application.name}`)); console.log(chalk.white(`UUID: ${application.uuid}`)); console.log(chalk.white(`Platform: ${application.platform}`)); console.log(chalk.white(`URL: ${application.url}`)); } catch (error) { throw new Error(`Failed to create application: ${error.message}`); } } async getApplicationLogs(uuid: string, options: { lines?: number; deployment?: string } = {}): Promise<void> { try { const config = await this.configService.getConfig(); const auth = await this.authService.getAuth(); const params = new URLSearchParams(); if (options.lines) params.append('lines', options.lines.toString()); if (options.deployment) params.append('deployment', options.deployment); const response = await axios.get(`${config.apiUrl}/api/applications/${uuid}/logs?${params}`, { headers: { 'Authorization': `Bearer ${auth.token}`, 'Content-Type': 'application/json' }, timeout: 10000 }); const data = response.data; console.log(chalk.cyan.bold(`\nπŸ“‹ Application Logs - ${data.application}`)); console.log(chalk.gray(`Deployment: ${data.deployment} | Lines: ${data.logs.length}/${data.totalLines}`)); data.logs.forEach((log: DeploymentLog) => { const levelColor = log.level === 'error' ? chalk.red : log.level === 'warn' ? chalk.yellow : chalk.blue; const timestamp = new Date(log.timestamp).toLocaleTimeString(); console.log(`${chalk.gray(timestamp)} ${levelColor(log.level.toUpperCase().padEnd(5))} ${log.message}`); }); } catch (error) { throw new Error(`Failed to get application logs: ${error.message}`); } } async stopApplication(uuid: string): Promise<void> { try { const config = await this.configService.getConfig(); const auth = await this.authService.getAuth(); console.log(chalk.blue('πŸ”„ Stopping application...')); const response = await axios.post(`${config.apiUrl}/api/applications/${uuid}/stop`, {}, { headers: { 'Authorization': `Bearer ${auth.token}`, 'Content-Type': 'application/json' }, timeout: 30000 }); console.log(chalk.green('βœ… Application stopped successfully!')); console.log(chalk.white(`Application: ${response.data.application.name}`)); } catch (error) { throw new Error(`Failed to stop application: ${error.message}`); } } async startApplication(uuid: string): Promise<void> { try { const config = await this.configService.getConfig(); const auth = await this.authService.getAuth(); console.log(chalk.blue('πŸ”„ Starting application...')); const response = await axios.post(`${config.apiUrl}/api/applications/${uuid}/start`, {}, { headers: { 'Authorization': `Bearer ${auth.token}`, 'Content-Type': 'application/json' }, timeout: 30000 }); console.log(chalk.green('βœ… Application started successfully!')); console.log(chalk.white(`Application: ${response.data.application.name}`)); } catch (error) { throw new Error(`Failed to start application: ${error.message}`); } } private async monitorDeployment(uuid: string, deploymentId: string): Promise<void> { console.log(chalk.blue('πŸ”„ Monitoring deployment progress...')); // Simulate monitoring (in real implementation, this would poll the deployment status) const spinner = ['β ‹', 'β ™', 'β Ή', 'β Έ', 'β Ό', 'β ΄', 'β ¦', 'β §', 'β ‡', '⠏']; let i = 0; const interval = setInterval(() => { process.stdout.write(`\r${chalk.blue(spinner[i++ % spinner.length])} Deploying...`); }, 100); setTimeout(() => { clearInterval(interval); process.stdout.write('\r'); console.log(chalk.green('βœ… Deployment completed successfully!')); }, 5000); } }