@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
text/typescript
/**
* 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);
}
}