import { NupstSnmp } from './snmp/manager.js'; import { NupstDaemon } from './daemon.js'; import { NupstSystemd } from './systemd.js'; import { commitinfo } from './00_commitinfo_data.js'; import { spawn } from 'child_process'; import * as https from 'https'; /** * Main Nupst class that coordinates all components * Acts as a facade to access SNMP, Daemon, and Systemd functionality */ export class Nupst { private readonly snmp: NupstSnmp; private readonly daemon: NupstDaemon; private readonly systemd: NupstSystemd; private updateAvailable: boolean = false; private latestVersion: string = ''; /** * Create a new Nupst instance with all necessary components */ constructor() { this.snmp = new NupstSnmp(); this.snmp.setNupst(this); // Set up bidirectional reference this.daemon = new NupstDaemon(this.snmp); this.systemd = new NupstSystemd(this.daemon); } /** * Get the SNMP manager for UPS communication */ public getSnmp(): NupstSnmp { return this.snmp; } /** * Get the daemon manager for background monitoring */ public getDaemon(): NupstDaemon { return this.daemon; } /** * Get the systemd manager for service operations */ public getSystemd(): NupstSystemd { return this.systemd; } /** * Get the current version of NUPST * @returns The current version string */ public getVersion(): string { return commitinfo.version; } /** * Check if an update is available * @returns Promise resolving to true if an update is available */ public async checkForUpdates(): Promise { try { const latestVersion = await this.getLatestVersion(); const currentVersion = this.getVersion(); // Compare versions this.updateAvailable = this.compareVersions(latestVersion, currentVersion) > 0; this.latestVersion = latestVersion; return this.updateAvailable; } catch (error) { console.error(`Error checking for updates: ${error.message}`); return false; } } /** * Get update status information * @returns Object with update status information */ public getUpdateStatus(): { currentVersion: string, latestVersion: string, updateAvailable: boolean } { return { currentVersion: this.getVersion(), latestVersion: this.latestVersion || this.getVersion(), updateAvailable: this.updateAvailable }; } /** * Get the latest version from npm registry * @returns Promise resolving to the latest version string */ private async getLatestVersion(): Promise { return new Promise((resolve, reject) => { const options = { hostname: 'registry.npmjs.org', path: '/@serve.zone/nupst', method: 'GET', headers: { 'Accept': 'application/json', 'User-Agent': `nupst/${this.getVersion()}` } }; const req = https.request(options, (res) => { let data = ''; res.on('data', (chunk) => { data += chunk; }); res.on('end', () => { try { const response = JSON.parse(data); if (response['dist-tags'] && response['dist-tags'].latest) { resolve(response['dist-tags'].latest); } else { reject(new Error('Failed to parse version from npm registry response')); } } catch (error) { reject(error); } }); }); req.on('error', (error) => { reject(error); }); req.end(); }); } /** * Compare two semantic version strings * @param versionA First version * @param versionB Second version * @returns -1 if versionA < versionB, 0 if equal, 1 if versionA > versionB */ private compareVersions(versionA: string, versionB: string): number { const partsA = versionA.split('.').map(part => parseInt(part, 10)); const partsB = versionB.split('.').map(part => parseInt(part, 10)); for (let i = 0; i < Math.max(partsA.length, partsB.length); i++) { const partA = i < partsA.length ? partsA[i] : 0; const partB = i < partsB.length ? partsB[i] : 0; if (partA > partB) return 1; if (partA < partB) return -1; } return 0; // Versions are equal } /** * Log the current version and update status */ public logVersionInfo(checkForUpdates: boolean = true): void { const version = this.getVersion(); console.log('┌─ NUPST Version ────────────────────────┐'); console.log(`│ Current Version: ${version}`); if (this.updateAvailable && this.latestVersion) { console.log(`│ Update Available: ${this.latestVersion}`); console.log('│ Run "sudo nupst update" to update'); } else if (checkForUpdates) { console.log('│ Checking for updates...'); this.checkForUpdates().then(updateAvailable => { if (updateAvailable) { console.log(`│ Update Available: ${this.latestVersion}`); console.log('│ Run "sudo nupst update" to update'); } else { console.log('│ You are running the latest version'); } console.log('└──────────────────────────────────────────┘'); }).catch(() => { console.log('│ Could not check for updates'); console.log('└──────────────────────────────────────────┘'); }); } else { console.log('└──────────────────────────────────────────┘'); } } }