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
JavaScript
;
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