deploy-neex
Version:
š CLI tool for deploying Neex applications with PM2 and Nginx
182 lines (179 loc) ⢠7.68 kB
JavaScript
import { Logger } from './utils/logger.js';
import { SystemUtils } from './utils/system.js';
import { PM2Generator } from './generators/pm2.js';
import { NginxGenerator } from './generators/nginx.js';
export class Deployer {
logger;
system;
pm2;
nginx;
constructor() {
this.logger = new Logger();
this.system = new SystemUtils(this.logger);
this.pm2 = new PM2Generator(this.logger, this.system);
this.nginx = new NginxGenerator(this.logger, this.system);
}
async deploy(config, project) {
this.logger.info(`š Starting deployment of ${config.projectName}`);
try {
// Step 1: Prerequisites
await this.checkPrerequisites(project);
// Step 2: Build project
await this.buildProject(project);
// Step 3: Generate environment file
await this.generateEnvironment(config, project);
// Step 4: Setup PM2
await this.setupPM2(config, project);
// Step 5: Setup Nginx (if requested)
if (config.nginxConfig) {
await this.setupNginx(config, project);
}
// Step 6: Create management scripts
await this.createManagementScripts(config, project);
// Step 7: Final checks
await this.performFinalChecks(config, project);
this.logger.success(`š Deployment completed successfully!`);
this.printPostDeploymentInfo(config, project);
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
this.logger.error(`Deployment failed: ${errorMessage}`);
throw error;
}
}
async checkPrerequisites(project) {
this.logger.step('Checking prerequisites...');
// Check Node.js
if (!await this.system.checkCommand('node')) {
throw new Error('Node.js is not installed');
}
// Check package manager
if (!await this.system.checkCommand(project.packageManager)) {
throw new Error(`${project.packageManager} is not installed`);
}
this.logger.success('Prerequisites checked');
}
async buildProject(project) {
this.logger.step('Building project...');
this.logger.startSpinner('Installing dependencies...');
await this.system.executeCommand(project.packageManager, ['install'], project.rootPath);
this.logger.updateSpinner('Building applications...');
await this.system.executeCommand(project.packageManager, ['run', 'build'], project.rootPath);
this.logger.stopSpinner();
this.logger.success('Project built successfully');
}
async generateEnvironment(config, project) {
const envPath = `${project.rootPath}/.env`;
const envExists = await this.system.checkCommand(`test -f ${envPath}`);
if (!envExists) {
const envContent = `NODE_ENV=${config.environment}
DATABASE_URL="your-database-connection-string"
PORT_CLIENT=${config.clientPort}
PORT_SERVER=${config.serverPort}
# Add your other environment variables here
`;
await this.system.writeFile(envPath, envContent);
this.logger.success('.env file created');
this.logger.warning('Please update .env with your actual values');
}
else {
this.logger.success('.env file already exists');
}
}
async setupPM2(config, project) {
this.logger.step('Setting up PM2...');
await this.pm2.install();
await this.pm2.generate(config, project);
await this.pm2.start(config, project);
}
async setupNginx(config, project) {
this.logger.step('Setting up Nginx...');
try {
await this.nginx.install();
await this.nginx.generate(config, project);
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
this.logger.warning(`Nginx setup requires manual intervention: ${errorMessage}`);
}
}
async createManagementScripts(config, project) {
this.logger.step('Creating management scripts...');
// Status script
const statusScript = `#!/bin/bash
echo "=== PM2 Status ==="
pm2 status
echo -e "\\n=== PM2 Logs (last 20 lines) ==="
pm2 logs --lines 20
echo -e "\\n=== Port Status ==="
netstat -tulpn | grep -E ":(${config.clientPort}|${config.serverPort}|80|443)" || true
echo -e "\\n=== System Resources ==="
df -h
free -h 2>/dev/null || top -l 1 | grep -E "^(Processes|PhysMem)"
`;
await this.system.writeFile(`${project.rootPath}/status.sh`, statusScript);
await this.system.executeCommand('chmod', ['+x', 'status.sh'], project.rootPath);
// Restart script
const restartScript = `#!/bin/bash
echo "Restarting services..."
pm2 restart all
echo "Services restarted!"
`;
await this.system.writeFile(`${project.rootPath}/restart.sh`, restartScript);
await this.system.executeCommand('chmod', ['+x', 'restart.sh'], project.rootPath);
this.logger.success('Management scripts created');
}
async performFinalChecks(config, project) {
this.logger.step('Performing final checks...');
// Wait a moment for services to start
await new Promise(resolve => setTimeout(resolve, 3000));
// Check if ports are accessible
if (project.hasClient) {
const clientAvailable = await this.system.isPortAvailable(config.clientPort);
if (clientAvailable) {
this.logger.warning(`Client port ${config.clientPort} seems to be available (service might not be running)`);
}
else {
this.logger.success(`Client is running on port ${config.clientPort}`);
}
}
if (project.hasServer) {
const serverAvailable = await this.system.isPortAvailable(config.serverPort);
if (serverAvailable) {
this.logger.warning(`Server port ${config.serverPort} seems to be available (service might not be running)`);
}
else {
this.logger.success(`Server is running on port ${config.serverPort}`);
}
}
}
printPostDeploymentInfo(config, project) {
console.log('\n' + '='.repeat(60));
console.log('š DEPLOYMENT COMPLETED SUCCESSFULLY!');
console.log('='.repeat(60));
console.log('\nš Your application is now running:');
if (project.hasClient) {
console.log(` Frontend: http://localhost:${config.clientPort}`);
}
if (project.hasServer) {
console.log(` Backend: http://localhost:${config.serverPort}`);
}
if (config.domain !== 'localhost') {
console.log(` Public: http://${config.domain}`);
}
console.log('\nš§ Management commands:');
console.log(' Check status: ./status.sh');
console.log(' Restart: ./restart.sh');
console.log(' PM2 logs: pm2 logs');
console.log(' PM2 monitor: pm2 monit');
console.log('\nš Next steps:');
console.log(' 1. Update .env file with your actual values');
if (config.nginxConfig) {
console.log(' 2. Follow nginx-setup.md for Nginx configuration');
console.log(' 3. Setup SSL certificate for production');
}
console.log(' 4. Configure your firewall to allow HTTP/HTTPS traffic');
console.log('\n' + '='.repeat(60));
}
}
//# sourceMappingURL=deployer.js.map