const { logger } = require('../config/logs'); const fs = require('fs').promises; const path = require('path'); class BaseService { constructor(name, defaultConfig = {}) { this.name = name; this.defaultConfig = defaultConfig; this.config = {}; this.isRunning = false; this.status = 'stopped'; this.logger = logger; this.setupPath = path.join(process.cwd(), 'data', 'setup.json'); } async loadConfig() { try { const setupContent = await fs.readFile(this.setupPath, 'utf8'); const setup = JSON.parse(setupContent); // Retrieve the service configuration from setup.json const serviceConfig = setup[0]?.services?.[this.name] || {}; // Merge with the default configuration this.config = { ...this.defaultConfig, ...serviceConfig }; return this.config; } catch (error) { this.logger.error(`Error loading configuration for ${this.name}:`, error); this.config = this.defaultConfig; return this.config; } } async start() { if (this.isRunning) { this.logger.warn(`Service ${this.name} is already running`); return; } try { // Load the configuration before starting await this.loadConfig(); // Check if the service is enabled if (this.config.enabled !== 'on') { this.logger.info(`Service ${this.name} is not enabled in the configuration`); return; } await this._startImplementation(); this.isRunning = true; this.status = 'running'; this.logger.info(`Service ${this.name} started successfully`); } catch (error) { this.logger.error(`Error starting service ${this.name}:`, error); this.status = 'error'; throw error; } } async stop() { if (!this.isRunning) { this.logger.warn(`Service ${this.name} is not running`); return; } try { await this._stopImplementation(); this.isRunning = false; this.status = 'stopped'; this.logger.info(`Service ${this.name} stopped successfully`); } catch (error) { this.logger.error(`Error stopping service ${this.name}:`, error); this.status = 'error'; throw error; } } getStatus() { return { name: this.name, status: this.status, isRunning: this.isRunning, config: this.config }; } async updateConfig(newConfig) { // Load the current configuration from setup.json let setup; try { const setupContent = await fs.readFile(this.setupPath, 'utf8'); setup = JSON.parse(setupContent); } catch (error) { throw new Error(`Error reading setup.json: ${error.message}`); } // Update the service configuration if (!setup[0].services) { setup[0].services = {}; } setup[0].services[this.name] = { ...this.config, ...newConfig }; // Save to setup.json try { await fs.writeFile(this.setupPath, JSON.stringify(setup, null, 2)); this.config = setup[0].services[this.name]; this.logger.info(`Configuration for service ${this.name} updated:`, this.config); } catch (error) { throw new Error(`Error saving configuration: ${error.message}`); } } // These methods must be implemented by subclasses async _startImplementation() { throw new Error('_startImplementation must be implemented by the subclass'); } async _stopImplementation() { throw new Error('_stopImplementation must be implemented by the subclass'); } } module.exports = BaseService;