UNPKG

@aerocorp/cli

Version:

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

195 lines (158 loc) • 6.39 kB
import axios from 'axios'; import chalk from 'chalk'; import ora from 'ora'; import { AuthService } from './auth'; export class ProjectService { private authService = new AuthService(); async list(options: any) { if (!this.authService.isAuthenticated()) { throw new Error('Not authenticated. Run "aerocorp login" first.'); } const spinner = ora('Fetching projects...').start(); try { const coolifyUrl = this.authService.getCoolifyUrl(); const headers = this.authService.getAuthHeaders(); // Get projects const projectsResponse = await axios.get(`${coolifyUrl}/api/v1/projects`, { headers }); const projects = projectsResponse.data; // Get applications for each project const projectsWithApps = await Promise.all( projects.map(async (project: any) => { try { const appsResponse = await axios.get( `${coolifyUrl}/api/v1/projects/${project.id}/applications`, { headers } ); return { ...project, applications: appsResponse.data || [] }; } catch (error) { return { ...project, applications: [] }; } }) ); spinner.succeed('Projects fetched successfully'); if (options.format === 'json') { console.log(JSON.stringify(projectsWithApps, null, 2)); return; } // Display in table format this.displayProjectsTable(projectsWithApps); } catch (error) { spinner.fail('Failed to fetch projects'); if (error.response?.status === 401) { throw new Error('Authentication failed. Please run "aerocorp login" again.'); } else if (error.response?.status === 403) { throw new Error('Access forbidden. Check your API token permissions.'); } else { throw new Error(`API Error: ${error.response?.data?.message || error.message}`); } } } private displayProjectsTable(projects: any[]) { console.log(chalk.cyan('\nšŸ“‹ AeroCorp Projects & Applications')); console.log(chalk.cyan('=====================================')); if (projects.length === 0) { console.log(chalk.yellow('⚠ No projects found')); return; } projects.forEach((project, index) => { console.log(chalk.blue(`\n${index + 1}. ${project.name}`)); console.log(chalk.gray(` UUID: ${project.uuid}`)); console.log(chalk.gray(` Description: ${project.description || 'No description'}`)); if (project.applications && project.applications.length > 0) { console.log(chalk.green(` Applications (${project.applications.length}):`)); project.applications.forEach((app: any, appIndex: number) => { const status = this.getStatusIcon(app.status); const url = app.url ? chalk.blue(app.url) : chalk.gray('No URL'); console.log(chalk.white(` ${appIndex + 1}. ${status} ${app.name}`)); console.log(chalk.gray(` Environment: ${app.environment || 'default'}`)); console.log(chalk.gray(` URL: ${url}`)); console.log(chalk.gray(` Status: ${app.status || 'unknown'}`)); if (app.last_deployment) { const deployTime = new Date(app.last_deployment).toLocaleString(); console.log(chalk.gray(` Last Deploy: ${deployTime}`)); } }); } else { console.log(chalk.gray(' Applications: None')); } }); // Summary const totalApps = projects.reduce((sum, project) => sum + (project.applications?.length || 0), 0); console.log(chalk.cyan(`\nšŸ“Š Summary: ${projects.length} projects, ${totalApps} applications`)); } private getStatusIcon(status?: string): string { switch (status?.toLowerCase()) { case 'running': case 'active': case 'healthy': return chalk.green('ā—'); case 'stopped': case 'inactive': return chalk.red('ā—'); case 'building': case 'deploying': return chalk.yellow('ā—'); case 'error': case 'failed': return chalk.red('āœ—'); default: return chalk.gray('ā—‹'); } } async create(name: string, description?: string) { if (!this.authService.isAuthenticated()) { throw new Error('Not authenticated. Run "aerocorp login" first.'); } const spinner = ora(`Creating project: ${name}...`).start(); try { const coolifyUrl = this.authService.getCoolifyUrl(); const headers = this.authService.getAuthHeaders(); const response = await axios.post( `${coolifyUrl}/api/v1/projects`, { name, description: description || `AeroCorp project: ${name}` }, { headers } ); spinner.succeed(`Project '${name}' created successfully`); console.log(chalk.green('āœ“ Project created')); console.log(chalk.blue(`šŸ“¦ Name: ${response.data.name}`)); console.log(chalk.blue(`šŸ†” UUID: ${response.data.uuid}`)); return response.data; } catch (error) { spinner.fail(`Failed to create project: ${name}`); if (error.response?.status === 409) { throw new Error(`Project '${name}' already exists`); } else { throw new Error(`API Error: ${error.response?.data?.message || error.message}`); } } } async delete(projectId: string) { if (!this.authService.isAuthenticated()) { throw new Error('Not authenticated. Run "aerocorp login" first.'); } const spinner = ora(`Deleting project: ${projectId}...`).start(); try { const coolifyUrl = this.authService.getCoolifyUrl(); const headers = this.authService.getAuthHeaders(); await axios.delete(`${coolifyUrl}/api/v1/projects/${projectId}`, { headers }); spinner.succeed(`Project '${projectId}' deleted successfully`); console.log(chalk.green('āœ“ Project deleted')); } catch (error) { spinner.fail(`Failed to delete project: ${projectId}`); if (error.response?.status === 404) { throw new Error(`Project '${projectId}' not found`); } else { throw new Error(`API Error: ${error.response?.data?.message || error.message}`); } } } }