fix(core): tidy formatting and minor fixes across CLI, SNMP, HTTP server, migrations and packaging

This commit is contained in:
2026-01-29 17:10:17 +00:00
parent fda072d15e
commit ff2dc00f31
31 changed files with 693 additions and 362 deletions

187
ts/cli.ts
View File

@@ -1,7 +1,7 @@
import { execSync } from 'node:child_process';
import { Nupst } from './nupst.ts';
import { logger, type ITableColumn } from './logger.ts';
import { theme, symbols } from './colors.ts';
import { type ITableColumn, logger } from './logger.ts';
import { symbols, theme } from './colors.ts';
/**
* Class for handling CLI commands
@@ -287,10 +287,15 @@ export class NupstCli {
try {
await this.nupst.getDaemon().loadConfig();
} catch (_error) {
logger.logBox('Configuration Error', [
'No configuration found.',
"Please run 'nupst ups add' first to create a configuration.",
], 50, 'error');
logger.logBox(
'Configuration Error',
[
'No configuration found.',
"Please run 'nupst ups add' first to create a configuration.",
],
50,
'error',
);
return;
}
@@ -300,17 +305,22 @@ export class NupstCli {
// Check if multi-UPS config
if (config.upsDevices && Array.isArray(config.upsDevices)) {
// === Multi-UPS Configuration ===
// Overview Box
logger.log('');
logger.logBox('NUPST Configuration', [
`UPS Devices: ${theme.highlight(String(config.upsDevices.length))}`,
`Groups: ${theme.highlight(String(config.groups ? config.groups.length : 0))}`,
`Check Interval: ${theme.info(String(config.checkInterval / 1000))} seconds`,
'',
theme.dim('Configuration File:'),
` ${theme.path('/etc/nupst/config.json')}`,
], 60, 'info');
logger.logBox(
'NUPST Configuration',
[
`UPS Devices: ${theme.highlight(String(config.upsDevices.length))}`,
`Groups: ${theme.highlight(String(config.groups ? config.groups.length : 0))}`,
`Check Interval: ${theme.info(String(config.checkInterval / 1000))} seconds`,
'',
theme.dim('Configuration File:'),
` ${theme.path('/etc/nupst/config.json')}`,
],
60,
'info',
);
// HTTP Server Status (if configured)
if (config.httpServer) {
@@ -319,17 +329,24 @@ export class NupstCli {
: theme.dim('Disabled');
logger.log('');
logger.logBox('HTTP Server', [
`Status: ${serverStatus}`,
...(config.httpServer.enabled ? [
`Port: ${theme.highlight(String(config.httpServer.port))}`,
`Path: ${theme.highlight(config.httpServer.path)}`,
`Auth Token: ${theme.dim('***' + config.httpServer.authToken.slice(-4))}`,
'',
theme.dim('Usage:'),
` curl -H "Authorization: Bearer TOKEN" http://localhost:${config.httpServer.port}${config.httpServer.path}`,
] : []),
], 70, config.httpServer.enabled ? 'success' : 'default');
logger.logBox(
'HTTP Server',
[
`Status: ${serverStatus}`,
...(config.httpServer.enabled
? [
`Port: ${theme.highlight(String(config.httpServer.port))}`,
`Path: ${theme.highlight(config.httpServer.path)}`,
`Auth Token: ${theme.dim('***' + config.httpServer.authToken.slice(-4))}`,
'',
theme.dim('Usage:'),
` curl -H "Authorization: Bearer TOKEN" http://localhost:${config.httpServer.port}${config.httpServer.path}`,
]
: []),
],
70,
config.httpServer.enabled ? 'success' : 'default',
);
}
// UPS Devices Table
@@ -369,8 +386,8 @@ export class NupstCli {
id: theme.dim(group.id),
mode: group.mode,
upsCount: String(upsInGroup.length),
ups: upsInGroup.length > 0
? upsInGroup.map((ups) => ups.name).join(', ')
ups: upsInGroup.length > 0
? upsInGroup.map((ups) => ups.name).join(', ')
: theme.dim('None'),
description: group.description || theme.dim('—'),
};
@@ -392,62 +409,68 @@ export class NupstCli {
}
} else {
// === Legacy Single UPS Configuration ===
if (!config.snmp) {
logger.logBox('Configuration Error', [
'Error: Legacy configuration missing SNMP settings',
], 60, 'error');
logger.logBox(
'Configuration Error',
[
'Error: Legacy configuration missing SNMP settings',
],
60,
'error',
);
return;
}
logger.log('');
logger.logBox('NUPST Configuration (Legacy)', [
theme.warning('Legacy single-UPS configuration format'),
'',
theme.dim('SNMP Settings:'),
` Host: ${theme.info(config.snmp.host)}`,
` Port: ${theme.info(String(config.snmp.port))}`,
` Version: ${config.snmp.version}`,
` UPS Model: ${config.snmp.upsModel || 'cyberpower'}`,
...(config.snmp.version === 1 || config.snmp.version === 2
? [` Community: ${config.snmp.community}`]
: []
),
...(config.snmp.version === 3
? [
logger.logBox(
'NUPST Configuration (Legacy)',
[
theme.warning('Legacy single-UPS configuration format'),
'',
theme.dim('SNMP Settings:'),
` Host: ${theme.info(config.snmp.host)}`,
` Port: ${theme.info(String(config.snmp.port))}`,
` Version: ${config.snmp.version}`,
` UPS Model: ${config.snmp.upsModel || 'cyberpower'}`,
...(config.snmp.version === 1 || config.snmp.version === 2
? [` Community: ${config.snmp.community}`]
: []),
...(config.snmp.version === 3
? [
` Security Level: ${config.snmp.securityLevel}`,
` Username: ${config.snmp.username}`,
...(config.snmp.securityLevel === 'authNoPriv' || config.snmp.securityLevel === 'authPriv'
...(config.snmp.securityLevel === 'authNoPriv' ||
config.snmp.securityLevel === 'authPriv'
? [` Auth Protocol: ${config.snmp.authProtocol || 'None'}`]
: []
),
: []),
...(config.snmp.securityLevel === 'authPriv'
? [` Privacy Protocol: ${config.snmp.privProtocol || 'None'}`]
: []
),
: []),
` Timeout: ${config.snmp.timeout / 1000} seconds`,
]
: []
),
...(config.snmp.upsModel === 'custom' && config.snmp.customOIDs
? [
: []),
...(config.snmp.upsModel === 'custom' && config.snmp.customOIDs
? [
theme.dim('Custom OIDs:'),
` Power Status: ${config.snmp.customOIDs.POWER_STATUS || 'Not set'}`,
` Battery Capacity: ${config.snmp.customOIDs.BATTERY_CAPACITY || 'Not set'}`,
` Battery Runtime: ${config.snmp.customOIDs.BATTERY_RUNTIME || 'Not set'}`,
]
: []
),
'',
` Check Interval: ${config.checkInterval / 1000} seconds`,
'',
theme.dim('Configuration File:'),
` ${theme.path('/etc/nupst/config.json')}`,
'',
theme.warning('Note: Using legacy single-UPS configuration format.'),
`Consider using ${theme.command('nupst ups add')} to migrate to multi-UPS format.`,
], 70, 'warning');
: []),
'',
` Check Interval: ${config.checkInterval / 1000} seconds`,
'',
theme.dim('Configuration File:'),
` ${theme.path('/etc/nupst/config.json')}`,
'',
theme.warning('Note: Using legacy single-UPS configuration format.'),
`Consider using ${theme.command('nupst ups add')} to migrate to multi-UPS format.`,
],
70,
'warning',
);
}
// Service Status
@@ -458,10 +481,15 @@ export class NupstCli {
execSync('systemctl is-enabled nupst.service || true').toString().trim() === 'enabled';
logger.log('');
logger.logBox('Service Status', [
`Active: ${isActive ? theme.success('Yes') : theme.dim('No')}`,
`Enabled: ${isEnabled ? theme.success('Yes') : theme.dim('No')}`,
], 50, isActive ? 'success' : 'default');
logger.logBox(
'Service Status',
[
`Active: ${isActive ? theme.success('Yes') : theme.dim('No')}`,
`Enabled: ${isEnabled ? theme.success('Yes') : theme.dim('No')}`,
],
50,
isActive ? 'success' : 'default',
);
logger.log('');
} catch (_error) {
// Ignore errors checking service status
@@ -514,8 +542,16 @@ export class NupstCli {
// Service subcommands
logger.log(theme.info('Service Subcommands:'));
this.printCommand('nupst service enable', 'Install and enable systemd service', theme.dim('(requires root)'));
this.printCommand('nupst service disable', 'Stop and disable systemd service', theme.dim('(requires root)'));
this.printCommand(
'nupst service enable',
'Install and enable systemd service',
theme.dim('(requires root)'),
);
this.printCommand(
'nupst service disable',
'Stop and disable systemd service',
theme.dim('(requires root)'),
);
this.printCommand('nupst service start', 'Start the systemd service');
this.printCommand('nupst service stop', 'Stop the systemd service');
this.printCommand('nupst service restart', 'Restart the systemd service');
@@ -545,7 +581,10 @@ export class NupstCli {
logger.log(theme.info('Action Subcommands:'));
this.printCommand('nupst action add <target-id>', 'Add a new action to a UPS or group');
this.printCommand('nupst action remove <target-id> <index>', 'Remove an action by index');
this.printCommand('nupst action list [target-id]', 'List all actions (optionally for specific target)');
this.printCommand(
'nupst action list [target-id]',
'List all actions (optionally for specific target)',
);
console.log('');
// Feature subcommands