@aerocorp/cli
Version:
AeroCorp CLI 5.1.0 - Future-Proofed Enterprise Infrastructure with Live Preview, Tunneling & Advanced DevOps
233 lines • 10.7 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DeployService = void 0;
const axios_1 = __importDefault(require("axios"));
const chalk_1 = __importDefault(require("chalk"));
const ora_1 = __importDefault(require("ora"));
const fs_1 = require("fs");
const auth_1 = require("./auth");
const config_1 = require("./config");
class DeployService {
constructor() {
this.authService = new auth_1.AuthService();
this.configService = new config_1.ConfigService();
}
async deploy(options) {
console.log(chalk_1.default.cyan('╔═══════════════════════╗'));
console.log(chalk_1.default.cyan('║ AeroCorp Deployment ║'));
console.log(chalk_1.default.cyan('╚═══════════════════════╝'));
// Check authentication
if (!this.authService.isAuthenticated()) {
throw new Error('Not authenticated. Run "aerocorp login" first.');
}
const spinner = (0, ora_1.default)('Preparing deployment...').start();
try {
// Read project configuration
const projectConfig = await this.readProjectConfig();
const deploymentConfig = this.buildDeploymentConfig(options, projectConfig);
spinner.text = 'Creating deployment...';
// Get Coolify API details
const coolifyUrl = this.authService.getCoolifyUrl();
const headers = this.authService.getAuthHeaders();
// Create or update application
const appResponse = await this.createOrUpdateApplication(coolifyUrl, headers, deploymentConfig);
spinner.text = 'Starting deployment...';
// Trigger deployment
const deployResponse = await this.triggerDeployment(coolifyUrl, headers, appResponse.data, deploymentConfig);
spinner.succeed('Deployment initiated successfully');
console.log(chalk_1.default.green('✓ Deployment started'));
console.log(chalk_1.default.blue(`📦 Application: ${deploymentConfig.name}`));
console.log(chalk_1.default.blue(`🌍 Environment: ${deploymentConfig.environment}`));
console.log(chalk_1.default.blue(`🔗 URL: ${deployResponse.url || 'Pending...'}`));
// Monitor deployment if requested
if (options.follow || options.watch) {
await this.monitorDeployment(coolifyUrl, headers, deployResponse.id);
}
return deployResponse;
}
catch (error) {
spinner.fail('Deployment failed');
throw error;
}
}
async readProjectConfig() {
const configFiles = [
'aerocorp.json',
'aerocorp.yml',
'aerocorp.yaml',
'package.json',
'docker-compose.yml',
'Dockerfile'
];
let config = {};
for (const file of configFiles) {
if ((0, fs_1.existsSync)(file)) {
try {
if (file.endsWith('.json')) {
const content = (0, fs_1.readFileSync)(file, 'utf8');
const parsed = JSON.parse(content);
if (file === 'package.json') {
config = {
name: parsed.name,
version: parsed.version,
description: parsed.description,
scripts: parsed.scripts,
dependencies: parsed.dependencies,
...config
};
}
else {
config = { ...config, ...parsed };
}
}
}
catch (error) {
console.warn(chalk_1.default.yellow(`⚠ Could not parse ${file}: ${error.message}`));
}
}
}
return config;
}
buildDeploymentConfig(options, projectConfig) {
const environment = options.prod ? 'production' :
options.staging ? 'staging' :
options.preview ? 'preview' : 'development';
return {
name: options.name || projectConfig.name || 'aerocorp-app',
environment,
force: options.force || false,
buildEnv: this.parseEnvString(options.buildEnv),
runtimeEnv: this.parseEnvString(options.env),
regions: options.region ? options.region.split(',') : ['default'],
replicas: parseInt(options.scale) || 1,
projectConfig,
source: {
type: 'git',
repository: process.cwd(),
branch: 'main'
}
};
}
parseEnvString(envString) {
if (!envString)
return {};
const env = {};
const pairs = envString.split(',');
for (const pair of pairs) {
const [key, ...valueParts] = pair.split('=');
if (key && valueParts.length > 0) {
env[key.trim()] = valueParts.join('=').trim();
}
}
return env;
}
async createOrUpdateApplication(coolifyUrl, headers, config) {
try {
// First, try to get existing applications
const appsResponse = await axios_1.default.get(`${coolifyUrl}/api/v1/applications`, { headers });
const existingApp = appsResponse.data.find((app) => app.name === config.name);
if (existingApp) {
// Update existing application
const updateResponse = await axios_1.default.put(`${coolifyUrl}/api/v1/applications/${existingApp.id}`, {
name: config.name,
description: config.projectConfig.description,
environment: config.environment,
build_env: config.buildEnv,
runtime_env: config.runtimeEnv
}, { headers });
return updateResponse;
}
else {
// Create new application
const createResponse = await axios_1.default.post(`${coolifyUrl}/api/v1/applications`, {
name: config.name,
description: config.projectConfig.description || 'AeroCorp Application',
environment: config.environment,
source: config.source,
build_env: config.buildEnv,
runtime_env: config.runtimeEnv,
replicas: config.replicas
}, { headers });
return createResponse;
}
}
catch (error) {
if (error.response?.status === 404) {
// Fallback: create application in default project
const projectsResponse = await axios_1.default.get(`${coolifyUrl}/api/v1/projects`, { headers });
const defaultProject = projectsResponse.data[0];
if (!defaultProject) {
throw new Error('No projects found. Please create a project in Coolify first.');
}
const createResponse = await axios_1.default.post(`${coolifyUrl}/api/v1/projects/${defaultProject.id}/applications`, {
name: config.name,
description: config.projectConfig.description || 'AeroCorp Application',
environment: config.environment,
source: config.source,
build_env: config.buildEnv,
runtime_env: config.runtimeEnv,
replicas: config.replicas
}, { headers });
return createResponse;
}
throw error;
}
}
async triggerDeployment(coolifyUrl, headers, application, config) {
const deployResponse = await axios_1.default.post(`${coolifyUrl}/api/v1/applications/${application.id}/deploy`, {
force: config.force,
environment: config.environment
}, { headers });
return {
id: deployResponse.data.id || application.id,
url: deployResponse.data.url || application.url,
status: deployResponse.data.status || 'pending',
application: application
};
}
async monitorDeployment(coolifyUrl, headers, deploymentId) {
console.log(chalk_1.default.blue('\n📊 Monitoring deployment...'));
const spinner = (0, ora_1.default)('Deployment in progress...').start();
let attempts = 0;
const maxAttempts = 60; // 5 minutes with 5-second intervals
while (attempts < maxAttempts) {
try {
const statusResponse = await axios_1.default.get(`${coolifyUrl}/api/v1/deployments/${deploymentId}`, { headers });
const status = statusResponse.data.status;
switch (status) {
case 'success':
case 'completed':
spinner.succeed('Deployment completed successfully');
console.log(chalk_1.default.green('🎉 Your application is now live!'));
return;
case 'failed':
case 'error':
spinner.fail('Deployment failed');
console.log(chalk_1.default.red('❌ Deployment failed. Check logs for details.'));
return;
case 'building':
spinner.text = 'Building application...';
break;
case 'deploying':
spinner.text = 'Deploying application...';
break;
default:
spinner.text = `Status: ${status}`;
}
await new Promise(resolve => setTimeout(resolve, 5000));
attempts++;
}
catch (error) {
console.warn(chalk_1.default.yellow(`⚠ Could not fetch deployment status: ${error.message}`));
break;
}
}
spinner.warn('Deployment monitoring timed out');
console.log(chalk_1.default.yellow('⏰ Deployment is still in progress. Check Coolify dashboard for updates.'));
}
}
exports.DeployService = DeployService;
//# sourceMappingURL=deploy.js.map