UNPKG

forge-deploy-cli

Version:

Professional CLI for local deployments with automatic subdomain routing, SSL certificates, and infrastructure management

276 lines (274 loc) 10.4 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.AutoRestartService = void 0; const fs_extra_1 = __importDefault(require("fs-extra")); const path_1 = __importDefault(require("path")); const child_process_1 = require("child_process"); const chalk_1 = __importDefault(require("chalk")); const system_1 = require("../utils/system"); class AutoRestartService { /** * Setup auto-restart for the Forge CLI */ static async setupAutoRestart() { try { console.log(chalk_1.default.cyan('Setting up auto-restart service...')); const config = await this.createConfig(); if ((0, system_1.isWindows)()) { await this.setupWindowsService(config); } else { await this.setupUnixService(config); } await this.saveConfig(config); console.log(chalk_1.default.green('Auto-restart service configured successfully')); } catch (error) { console.error(chalk_1.default.red(`Failed to setup auto-restart: ${error}`)); throw error; } } /** * Remove auto-restart service */ static async removeAutoRestart() { try { console.log(chalk_1.default.cyan('Removing auto-restart service...')); if ((0, system_1.isWindows)()) { await this.removeWindowsService(); } else { await this.removeUnixService(); } await this.removeConfig(); console.log(chalk_1.default.green('Auto-restart service removed successfully')); } catch (error) { console.error(chalk_1.default.red(`Failed to remove auto-restart: ${error}`)); throw error; } } /** * Check if auto-restart is enabled */ static async isAutoRestartEnabled() { try { const config = await this.loadConfig(); return config?.enabled || false; } catch { return false; } } /** * Start the auto-restart service */ static async startAutoRestart() { try { if ((0, system_1.isWindows)()) { (0, child_process_1.execSync)(`sc start ${this.SERVICE_NAME}`, { stdio: 'pipe' }); } else { (0, child_process_1.execSync)(`systemctl start ${this.SERVICE_NAME.toLowerCase()}`, { stdio: 'pipe' }); } console.log(chalk_1.default.green('Auto-restart service started')); } catch (error) { console.error(chalk_1.default.red(`Failed to start auto-restart service: ${error}`)); } } /** * Stop the auto-restart service */ static async stopAutoRestart() { try { if ((0, system_1.isWindows)()) { (0, child_process_1.execSync)(`sc stop ${this.SERVICE_NAME}`, { stdio: 'pipe' }); } else { (0, child_process_1.execSync)(`systemctl stop ${this.SERVICE_NAME.toLowerCase()}`, { stdio: 'pipe' }); } console.log(chalk_1.default.green('Auto-restart service stopped')); } catch (error) { console.error(chalk_1.default.red(`Failed to stop auto-restart service: ${error}`)); } } /** * Create configuration for auto-restart */ static async createConfig() { const executablePath = process.execPath; const workingDirectory = process.cwd(); await fs_extra_1.default.ensureDir(this.LOG_DIR); return { enabled: true, serviceName: this.SERVICE_NAME, executablePath, workingDirectory, logPath: path_1.default.join(this.LOG_DIR, 'forge-service.log'), restartDelay: 5000 }; } /** * Setup Windows service */ static async setupWindowsService(config) { // Create a batch file to start the service const batchContent = `@echo off cd /d "${config.workingDirectory}" "${config.executablePath}" --service >> "${config.logPath}" 2>&1 `; const batchPath = path_1.default.join(config.workingDirectory, 'forge-service.bat'); await fs_extra_1.default.writeFile(batchPath, batchContent); // Create the Windows service using sc command const serviceCommand = `sc create ${config.serviceName} binPath= "${batchPath}" start= auto DisplayName= "Forge CLI Auto-Restart Service"`; try { (0, child_process_1.execSync)(serviceCommand, { stdio: 'pipe' }); console.log(chalk_1.default.green(`Windows service '${config.serviceName}' created`)); } catch (error) { console.warn(chalk_1.default.yellow('Note: Creating Windows service requires administrator privileges')); console.log(chalk_1.default.gray('Run as administrator to enable auto-restart on system boot')); } } /** * Setup Unix/Linux service (systemd) */ static async setupUnixService(config) { const serviceContent = `[Unit] Description=Forge CLI Auto-Restart Service After=network.target [Service] Type=simple User=${process.env.USER || 'forge'} WorkingDirectory=${config.workingDirectory} ExecStart=${config.executablePath} --service Restart=always RestartSec=5 StandardOutput=append:${config.logPath} StandardError=append:${config.logPath} [Install] WantedBy=multi-user.target `; const servicePath = `/etc/systemd/system/${config.serviceName.toLowerCase()}.service`; try { await fs_extra_1.default.writeFile(servicePath, serviceContent); (0, child_process_1.execSync)('systemctl daemon-reload', { stdio: 'pipe' }); (0, child_process_1.execSync)(`systemctl enable ${config.serviceName.toLowerCase()}`, { stdio: 'pipe' }); console.log(chalk_1.default.green(`Systemd service '${config.serviceName}' created`)); } catch (error) { console.warn(chalk_1.default.yellow('Note: Creating systemd service requires root privileges')); console.log(chalk_1.default.gray('Run with sudo to enable auto-restart on system boot')); } } /** * Remove Windows service */ static async removeWindowsService() { try { (0, child_process_1.execSync)(`sc delete ${this.SERVICE_NAME}`, { stdio: 'pipe' }); // Clean up batch file const batchPath = path_1.default.join(process.cwd(), 'forge-service.bat'); if (await fs_extra_1.default.pathExists(batchPath)) { await fs_extra_1.default.remove(batchPath); } } catch (error) { console.warn(chalk_1.default.yellow(`Service removal failed: ${error}`)); } } /** * Remove Unix service */ static async removeUnixService() { try { const serviceName = this.SERVICE_NAME.toLowerCase(); (0, child_process_1.execSync)(`systemctl stop ${serviceName}`, { stdio: 'pipe' }); (0, child_process_1.execSync)(`systemctl disable ${serviceName}`, { stdio: 'pipe' }); const servicePath = `/etc/systemd/system/${serviceName}.service`; if (await fs_extra_1.default.pathExists(servicePath)) { await fs_extra_1.default.remove(servicePath); } (0, child_process_1.execSync)('systemctl daemon-reload', { stdio: 'pipe' }); } catch (error) { console.warn(chalk_1.default.yellow(`Service removal failed: ${error}`)); } } /** * Save configuration */ static async saveConfig(config) { const configPath = path_1.default.join(process.cwd(), this.CONFIG_FILE); await fs_extra_1.default.writeJSON(configPath, config, { spaces: 2 }); } /** * Load configuration */ static async loadConfig() { try { const configPath = path_1.default.join(process.cwd(), this.CONFIG_FILE); return await fs_extra_1.default.readJSON(configPath); } catch { return null; } } /** * Remove configuration */ static async removeConfig() { try { const configPath = path_1.default.join(process.cwd(), this.CONFIG_FILE); if (await fs_extra_1.default.pathExists(configPath)) { await fs_extra_1.default.remove(configPath); } } catch { // Ignore errors } } /** * Start the service daemon */ static async startServiceDaemon() { console.log(chalk_1.default.blue('Starting Forge CLI service daemon...')); const config = await this.loadConfig(); if (!config) { throw new Error('Auto-restart not configured'); } // Start the main process monitoring loop this.startMonitoringLoop(config); } /** * Monitoring loop for the service */ static startMonitoringLoop(config) { const startTime = Date.now(); console.log(chalk_1.default.green(`Forge CLI service started at ${new Date().toISOString()}`)); // Monitor for system events and restart if needed process.on('SIGTERM', () => { console.log(chalk_1.default.yellow('Service received SIGTERM, shutting down gracefully...')); process.exit(0); }); process.on('SIGINT', () => { console.log(chalk_1.default.yellow('Service received SIGINT, shutting down gracefully...')); process.exit(0); }); // Keep the process alive setInterval(() => { const uptime = Math.floor((Date.now() - startTime) / 1000); console.log(chalk_1.default.gray(`Service uptime: ${uptime} seconds`)); }, 60000); // Log every minute } } exports.AutoRestartService = AutoRestartService; AutoRestartService.CONFIG_FILE = 'forge-autorestart.json'; AutoRestartService.SERVICE_NAME = 'ForgeCliService'; AutoRestartService.LOG_DIR = path_1.default.join(process.cwd(), 'logs'); //# sourceMappingURL=autoRestart.js.map