227 lines
6.4 KiB
TypeScript
227 lines
6.4 KiB
TypeScript
import { NupstSnmp } from './snmp/manager.js';
|
|
import { NupstDaemon } from './daemon.js';
|
|
import { NupstSystemd } from './systemd.js';
|
|
import { commitinfo } from './00_commitinfo_data.js';
|
|
import { logger } from './logger.js';
|
|
import { UpsHandler } from './cli/ups-handler.js';
|
|
import { GroupHandler } from './cli/group-handler.js';
|
|
import { ServiceHandler } from './cli/service-handler.js';
|
|
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 readonly upsHandler: UpsHandler;
|
|
private readonly groupHandler: GroupHandler;
|
|
private readonly serviceHandler: ServiceHandler;
|
|
private updateAvailable: boolean = false;
|
|
private latestVersion: string = '';
|
|
|
|
/**
|
|
* Create a new Nupst instance with all necessary components
|
|
*/
|
|
constructor() {
|
|
// Initialize core components
|
|
this.snmp = new NupstSnmp();
|
|
this.snmp.setNupst(this); // Set up bidirectional reference
|
|
this.daemon = new NupstDaemon(this.snmp);
|
|
this.systemd = new NupstSystemd(this.daemon);
|
|
|
|
// Initialize handlers
|
|
this.upsHandler = new UpsHandler(this);
|
|
this.groupHandler = new GroupHandler(this);
|
|
this.serviceHandler = new ServiceHandler(this);
|
|
}
|
|
|
|
/**
|
|
* 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 UPS handler for UPS management
|
|
*/
|
|
public getUpsHandler(): UpsHandler {
|
|
return this.upsHandler;
|
|
}
|
|
|
|
/**
|
|
* Get the Group handler for group management
|
|
*/
|
|
public getGroupHandler(): GroupHandler {
|
|
return this.groupHandler;
|
|
}
|
|
|
|
/**
|
|
* Get the Service handler for service management
|
|
*/
|
|
public getServiceHandler(): ServiceHandler {
|
|
return this.serviceHandler;
|
|
}
|
|
|
|
/**
|
|
* 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<boolean> {
|
|
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) {
|
|
logger.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<string> {
|
|
return new Promise<string>((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();
|
|
const boxWidth = 45;
|
|
|
|
logger.logBoxTitle('NUPST Version', boxWidth);
|
|
logger.logBoxLine(`Current Version: ${version}`);
|
|
|
|
if (this.updateAvailable && this.latestVersion) {
|
|
logger.logBoxLine(`Update Available: ${this.latestVersion}`);
|
|
logger.logBoxLine('Run "sudo nupst update" to update');
|
|
logger.logBoxEnd();
|
|
} else if (checkForUpdates) {
|
|
logger.logBoxLine('Checking for updates...');
|
|
|
|
// We can't end the box yet since we're in an async operation
|
|
this.checkForUpdates().then(updateAvailable => {
|
|
if (updateAvailable) {
|
|
logger.logBoxLine(`Update Available: ${this.latestVersion}`);
|
|
logger.logBoxLine('Run "sudo nupst update" to update');
|
|
} else {
|
|
logger.logBoxLine('You are running the latest version');
|
|
}
|
|
logger.logBoxEnd();
|
|
}).catch(() => {
|
|
logger.logBoxLine('Could not check for updates');
|
|
logger.logBoxEnd();
|
|
});
|
|
} else {
|
|
logger.logBoxEnd();
|
|
}
|
|
}
|
|
} |