Compare commits
3 Commits
f860f39e59
...
39bf3e2239
Author | SHA1 | Date | |
---|---|---|---|
39bf3e2239 | |||
f3de3f0618 | |||
03056d279d |
@ -1,5 +1,13 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2025-03-26 - 2.6.15 - fix(logger)
|
||||||
|
Replace direct console logging with unified logger interface for consistent formatting
|
||||||
|
|
||||||
|
- Substitute console.log, console.error, and related calls with logger methods in cli, daemon, systemd, nupst, and index modules
|
||||||
|
- Integrate logBox formatting for structured output and consistent log presentation
|
||||||
|
- Update test expectations in test.logger.ts to check for standardized error messages
|
||||||
|
- Refactor logging calls throughout the codebase for improved clarity and maintainability
|
||||||
|
|
||||||
## 2025-03-26 - 2.6.14 - fix(systemd)
|
## 2025-03-26 - 2.6.14 - fix(systemd)
|
||||||
Shorten closing log divider in systemd service installation output for consistent formatting.
|
Shorten closing log divider in systemd service installation output for consistent formatting.
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@serve.zone/nupst",
|
"name": "@serve.zone/nupst",
|
||||||
"version": "2.6.14",
|
"version": "2.6.15",
|
||||||
"description": "Node.js UPS Shutdown Tool for SNMP-enabled UPS devices",
|
"description": "Node.js UPS Shutdown Tool for SNMP-enabled UPS devices",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"bin": {
|
"bin": {
|
||||||
@ -56,5 +56,6 @@
|
|||||||
"mongodb-memory-server",
|
"mongodb-memory-server",
|
||||||
"puppeteer"
|
"puppeteer"
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
"packageManager": "pnpm@10.7.0+sha512.6b865ad4b62a1d9842b61d674a393903b871d9244954f652b8842c2b553c72176b278f64c463e52d40fff8aba385c235c8c9ecf5cc7de4fd78b8bb6d49633ab6"
|
||||||
}
|
}
|
||||||
|
147
test/test.logger.ts
Normal file
147
test/test.logger.ts
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
import { tap, expect } from '@push.rocks/tapbundle';
|
||||||
|
import { Logger } from '../ts/logger.js';
|
||||||
|
|
||||||
|
// Create a Logger instance for testing
|
||||||
|
const logger = new Logger();
|
||||||
|
|
||||||
|
tap.test('should create a logger instance', async () => {
|
||||||
|
expect(logger instanceof Logger).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('should log messages with different log levels', async () => {
|
||||||
|
// We're not testing console output directly, just ensuring no errors
|
||||||
|
logger.log('Regular log message');
|
||||||
|
logger.error('Error message');
|
||||||
|
logger.warn('Warning message');
|
||||||
|
logger.success('Success message');
|
||||||
|
|
||||||
|
// Just assert that the test runs without errors
|
||||||
|
expect(true).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('should create a logbox with title, content, and end', async () => {
|
||||||
|
// Just ensuring no errors occur
|
||||||
|
logger.logBoxTitle('Test Box', 40);
|
||||||
|
logger.logBoxLine('This is a test line');
|
||||||
|
logger.logBoxEnd();
|
||||||
|
|
||||||
|
// Just assert that the test runs without errors
|
||||||
|
expect(true).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('should handle width persistence between logbox calls', async () => {
|
||||||
|
logger.logBoxTitle('Width Test', 45);
|
||||||
|
|
||||||
|
// These should use the width from the title
|
||||||
|
logger.logBoxLine('Line 1');
|
||||||
|
logger.logBoxLine('Line 2');
|
||||||
|
logger.logBoxEnd();
|
||||||
|
|
||||||
|
let errorThrown = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// This should work fine after the reset in logBoxEnd
|
||||||
|
logger.logBoxTitle('New Box', 30);
|
||||||
|
logger.logBoxLine('New line');
|
||||||
|
logger.logBoxEnd();
|
||||||
|
} catch (error) {
|
||||||
|
errorThrown = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(errorThrown).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('should throw error when using logBoxLine without width', async () => {
|
||||||
|
let errorThrown = false;
|
||||||
|
let errorMessage = '';
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Should throw because no width is set
|
||||||
|
logger.logBoxLine('This should fail');
|
||||||
|
} catch (error) {
|
||||||
|
errorThrown = true;
|
||||||
|
errorMessage = (error as Error).message;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(errorThrown).toBeTruthy();
|
||||||
|
expect(errorMessage).toBeTruthy();
|
||||||
|
expect(errorMessage.includes('No box width')).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('should create a complete logbox in one call', async () => {
|
||||||
|
// Just ensuring no errors occur
|
||||||
|
logger.logBox('Complete Box', [
|
||||||
|
'Line 1',
|
||||||
|
'Line 2',
|
||||||
|
'Line 3'
|
||||||
|
], 40);
|
||||||
|
|
||||||
|
// Just assert that the test runs without errors
|
||||||
|
expect(true).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('should handle content that exceeds box width', async () => {
|
||||||
|
// Just ensuring no errors occur when content is too long
|
||||||
|
logger.logBox('Truncation Test', [
|
||||||
|
'This line is way too long and should be truncated because it exceeds the available space'
|
||||||
|
], 30);
|
||||||
|
|
||||||
|
// Just assert that the test runs without errors
|
||||||
|
expect(true).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('should create dividers with custom characters', async () => {
|
||||||
|
// Just ensuring no errors occur
|
||||||
|
logger.logDivider(30);
|
||||||
|
logger.logDivider(20, '*');
|
||||||
|
|
||||||
|
// Just assert that the test runs without errors
|
||||||
|
expect(true).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('Logger Demo', async () => {
|
||||||
|
console.log('\n=== LOGGER DEMO ===\n');
|
||||||
|
|
||||||
|
// Basic logging
|
||||||
|
logger.log('Regular log message');
|
||||||
|
logger.error('Error message');
|
||||||
|
logger.warn('Warning message');
|
||||||
|
logger.success('Success message');
|
||||||
|
|
||||||
|
// Logbox with title, content lines, and end
|
||||||
|
logger.logBoxTitle('Configuration Loaded', 50);
|
||||||
|
logger.logBoxLine('SNMP Settings:');
|
||||||
|
logger.logBoxLine(' Host: 127.0.0.1');
|
||||||
|
logger.logBoxLine(' Port: 161');
|
||||||
|
logger.logBoxLine(' Version: 1');
|
||||||
|
logger.logBoxEnd();
|
||||||
|
|
||||||
|
// Complete logbox in one call
|
||||||
|
logger.logBox('UPS Status', [
|
||||||
|
'Power Status: onBattery',
|
||||||
|
'Battery Capacity: 75%',
|
||||||
|
'Runtime Remaining: 30 minutes'
|
||||||
|
], 45);
|
||||||
|
|
||||||
|
// Logbox with content that's too long for the width
|
||||||
|
logger.logBox('Truncation Example', [
|
||||||
|
'This line is short enough to fit within the box width',
|
||||||
|
'This line is way too long and will be truncated because it exceeds the available space for content within the logbox'
|
||||||
|
], 40);
|
||||||
|
|
||||||
|
// Demonstrating logbox width being remembered
|
||||||
|
logger.logBoxTitle('Width Persistence Example', 60);
|
||||||
|
logger.logBoxLine('These lines use the width from the title');
|
||||||
|
logger.logBoxLine('No need to specify the width again');
|
||||||
|
logger.logBoxEnd();
|
||||||
|
|
||||||
|
// Divider example
|
||||||
|
logger.log('\nDivider example:');
|
||||||
|
logger.logDivider(30);
|
||||||
|
logger.logDivider(30, '*');
|
||||||
|
|
||||||
|
expect(true).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Export the default tap object
|
||||||
|
export default tap.start();
|
@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@serve.zone/nupst',
|
name: '@serve.zone/nupst',
|
||||||
version: '2.6.14',
|
version: '2.6.15',
|
||||||
description: 'Node.js UPS Shutdown Tool for SNMP-enabled UPS devices'
|
description: 'Node.js UPS Shutdown Tool for SNMP-enabled UPS devices'
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ import { promises as fs } from 'fs';
|
|||||||
import { dirname, join } from 'path';
|
import { dirname, join } from 'path';
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
import { Nupst } from './nupst.js';
|
import { Nupst } from './nupst.js';
|
||||||
|
import { logger } from './logger.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for handling CLI commands
|
* Class for handling CLI commands
|
||||||
|
87
ts/daemon.ts
87
ts/daemon.ts
@ -4,6 +4,7 @@ import { exec, execFile } from 'child_process';
|
|||||||
import { promisify } from 'util';
|
import { promisify } from 'util';
|
||||||
import { NupstSnmp } from './snmp/manager.js';
|
import { NupstSnmp } from './snmp/manager.js';
|
||||||
import type { ISnmpConfig } from './snmp/types.js';
|
import type { ISnmpConfig } from './snmp/types.js';
|
||||||
|
import { logger } from './logger.js';
|
||||||
|
|
||||||
const execAsync = promisify(exec);
|
const execAsync = promisify(exec);
|
||||||
const execFileAsync = promisify(execFile);
|
const execFileAsync = promisify(execFile);
|
||||||
@ -147,11 +148,11 @@ export class NupstDaemon {
|
|||||||
*/
|
*/
|
||||||
public async start(): Promise<void> {
|
public async start(): Promise<void> {
|
||||||
if (this.isRunning) {
|
if (this.isRunning) {
|
||||||
console.log('Daemon is already running');
|
logger.log('Daemon is already running');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Starting NUPST daemon...');
|
logger.log('Starting NUPST daemon...');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Load configuration - this will throw an error if config doesn't exist
|
// Load configuration - this will throw an error if config doesn't exist
|
||||||
@ -165,11 +166,12 @@ export class NupstDaemon {
|
|||||||
this.snmp.getNupst().checkForUpdates().then(updateAvailable => {
|
this.snmp.getNupst().checkForUpdates().then(updateAvailable => {
|
||||||
if (updateAvailable) {
|
if (updateAvailable) {
|
||||||
const updateStatus = this.snmp.getNupst().getUpdateStatus();
|
const updateStatus = this.snmp.getNupst().getUpdateStatus();
|
||||||
console.log('┌─ Update Available ───────────────────────┐');
|
const boxWidth = 45;
|
||||||
console.log(`│ Current Version: ${updateStatus.currentVersion}`);
|
logger.logBoxTitle('Update Available', boxWidth);
|
||||||
console.log(`│ Latest Version: ${updateStatus.latestVersion}`);
|
logger.logBoxLine(`Current Version: ${updateStatus.currentVersion}`);
|
||||||
console.log('│ Run "sudo nupst update" to update');
|
logger.logBoxLine(`Latest Version: ${updateStatus.latestVersion}`);
|
||||||
console.log('└──────────────────────────────────────────┘');
|
logger.logBoxLine('Run "sudo nupst update" to update');
|
||||||
|
logger.logBoxEnd();
|
||||||
}
|
}
|
||||||
}).catch(() => {}); // Ignore errors checking for updates
|
}).catch(() => {}); // Ignore errors checking for updates
|
||||||
|
|
||||||
@ -178,7 +180,7 @@ export class NupstDaemon {
|
|||||||
await this.monitor();
|
await this.monitor();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.isRunning = false;
|
this.isRunning = false;
|
||||||
console.error(`Daemon failed to start: ${error.message}`);
|
logger.error(`Daemon failed to start: ${error.message}`);
|
||||||
process.exit(1); // Exit with error
|
process.exit(1); // Exit with error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -187,23 +189,24 @@ export class NupstDaemon {
|
|||||||
* Log the loaded configuration settings
|
* Log the loaded configuration settings
|
||||||
*/
|
*/
|
||||||
private logConfigLoaded(): void {
|
private logConfigLoaded(): void {
|
||||||
console.log('┌─ Configuration Loaded ─────────────────────┐');
|
const boxWidth = 50;
|
||||||
console.log('│ SNMP Settings:');
|
logger.logBoxTitle('Configuration Loaded', boxWidth);
|
||||||
console.log(`│ Host: ${this.config.snmp.host}`);
|
logger.logBoxLine('SNMP Settings:');
|
||||||
console.log(`│ Port: ${this.config.snmp.port}`);
|
logger.logBoxLine(` Host: ${this.config.snmp.host}`);
|
||||||
console.log(`│ Version: ${this.config.snmp.version}`);
|
logger.logBoxLine(` Port: ${this.config.snmp.port}`);
|
||||||
console.log('│ Thresholds:');
|
logger.logBoxLine(` Version: ${this.config.snmp.version}`);
|
||||||
console.log(`│ Battery: ${this.config.thresholds.battery}%`);
|
logger.logBoxLine('Thresholds:');
|
||||||
console.log(`│ Runtime: ${this.config.thresholds.runtime} minutes`);
|
logger.logBoxLine(` Battery: ${this.config.thresholds.battery}%`);
|
||||||
console.log(`│ Check Interval: ${this.config.checkInterval / 1000} seconds`);
|
logger.logBoxLine(` Runtime: ${this.config.thresholds.runtime} minutes`);
|
||||||
console.log('└────────────────────────────────────────────┘');
|
logger.logBoxLine(`Check Interval: ${this.config.checkInterval / 1000} seconds`);
|
||||||
|
logger.logBoxEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop the monitoring daemon
|
* Stop the monitoring daemon
|
||||||
*/
|
*/
|
||||||
public stop(): void {
|
public stop(): void {
|
||||||
console.log('Stopping NUPST daemon...');
|
logger.log('Stopping NUPST daemon...');
|
||||||
this.isRunning = false;
|
this.isRunning = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,7 +214,7 @@ export class NupstDaemon {
|
|||||||
* Monitor the UPS status and trigger shutdown when necessary
|
* Monitor the UPS status and trigger shutdown when necessary
|
||||||
*/
|
*/
|
||||||
private async monitor(): Promise<void> {
|
private async monitor(): Promise<void> {
|
||||||
console.log('Starting UPS monitoring...');
|
logger.log('Starting UPS monitoring...');
|
||||||
|
|
||||||
let lastStatus: 'online' | 'onBattery' | 'unknown' = 'unknown';
|
let lastStatus: 'online' | 'onBattery' | 'unknown' = 'unknown';
|
||||||
let lastLogTime = 0; // Track when we last logged status
|
let lastLogTime = 0; // Track when we last logged status
|
||||||
@ -226,20 +229,22 @@ export class NupstDaemon {
|
|||||||
|
|
||||||
// Log status changes
|
// Log status changes
|
||||||
if (status.powerStatus !== lastStatus) {
|
if (status.powerStatus !== lastStatus) {
|
||||||
console.log('┌─ Power Status Change ─────────────────────┐');
|
const statusBoxWidth = 45;
|
||||||
console.log(`│ Status changed: ${lastStatus} → ${status.powerStatus}`);
|
logger.logBoxTitle('Power Status Change', statusBoxWidth);
|
||||||
console.log('└───────────────────────────────────────────┘');
|
logger.logBoxLine(`Status changed: ${lastStatus} → ${status.powerStatus}`);
|
||||||
|
logger.logBoxEnd();
|
||||||
lastStatus = status.powerStatus;
|
lastStatus = status.powerStatus;
|
||||||
lastLogTime = currentTime; // Reset log timer when status changes
|
lastLogTime = currentTime; // Reset log timer when status changes
|
||||||
}
|
}
|
||||||
// Log status periodically (at least every 5 minutes)
|
// Log status periodically (at least every 5 minutes)
|
||||||
else if (shouldLogStatus) {
|
else if (shouldLogStatus) {
|
||||||
const timestamp = new Date().toISOString();
|
const timestamp = new Date().toISOString();
|
||||||
console.log('┌─ Periodic Status Update ──────────────────┐');
|
const periodicBoxWidth = 45;
|
||||||
console.log(`│ Timestamp: ${timestamp}`);
|
logger.logBoxTitle('Periodic Status Update', periodicBoxWidth);
|
||||||
console.log(`│ Power Status: ${status.powerStatus}`);
|
logger.logBoxLine(`Timestamp: ${timestamp}`);
|
||||||
console.log(`│ Battery: ${status.batteryCapacity}% | Runtime: ${status.batteryRuntime} min`);
|
logger.logBoxLine(`Power Status: ${status.powerStatus}`);
|
||||||
console.log('└───────────────────────────────────────────┘');
|
logger.logBoxLine(`Battery: ${status.batteryCapacity}% | Runtime: ${status.batteryRuntime} min`);
|
||||||
|
logger.logBoxEnd();
|
||||||
lastLogTime = currentTime;
|
lastLogTime = currentTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,7 +298,7 @@ export class NupstDaemon {
|
|||||||
* @param reason Reason for shutdown
|
* @param reason Reason for shutdown
|
||||||
*/
|
*/
|
||||||
public async initiateShutdown(reason: string): Promise<void> {
|
public async initiateShutdown(reason: string): Promise<void> {
|
||||||
console.log(`Initiating system shutdown due to: ${reason}`);
|
logger.log(`Initiating system shutdown due to: ${reason}`);
|
||||||
|
|
||||||
// Set a longer delay for shutdown to allow VMs and services to close
|
// Set a longer delay for shutdown to allow VMs and services to close
|
||||||
const shutdownDelayMinutes = 5;
|
const shutdownDelayMinutes = 5;
|
||||||
@ -312,7 +317,7 @@ export class NupstDaemon {
|
|||||||
try {
|
try {
|
||||||
if (fs.existsSync(path)) {
|
if (fs.existsSync(path)) {
|
||||||
shutdownCmd = path;
|
shutdownCmd = path;
|
||||||
console.log(`Found shutdown command at: ${shutdownCmd}`);
|
logger.log(`Found shutdown command at: ${shutdownCmd}`);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -322,32 +327,32 @@ export class NupstDaemon {
|
|||||||
|
|
||||||
if (shutdownCmd) {
|
if (shutdownCmd) {
|
||||||
// Execute shutdown command with delay to allow for VM graceful shutdown
|
// Execute shutdown command with delay to allow for VM graceful shutdown
|
||||||
console.log(`Executing: ${shutdownCmd} -h +${shutdownDelayMinutes} "UPS battery critical..."`);
|
logger.log(`Executing: ${shutdownCmd} -h +${shutdownDelayMinutes} "UPS battery critical..."`);
|
||||||
const { stdout } = await execFileAsync(shutdownCmd, [
|
const { stdout } = await execFileAsync(shutdownCmd, [
|
||||||
'-h',
|
'-h',
|
||||||
`+${shutdownDelayMinutes}`,
|
`+${shutdownDelayMinutes}`,
|
||||||
`UPS battery critical, shutting down in ${shutdownDelayMinutes} minutes`
|
`UPS battery critical, shutting down in ${shutdownDelayMinutes} minutes`
|
||||||
]);
|
]);
|
||||||
console.log('Shutdown initiated:', stdout);
|
logger.log(`Shutdown initiated: ${stdout}`);
|
||||||
console.log(`Allowing ${shutdownDelayMinutes} minutes for VMs to shut down safely`);
|
logger.log(`Allowing ${shutdownDelayMinutes} minutes for VMs to shut down safely`);
|
||||||
} else {
|
} else {
|
||||||
// Try using the PATH to find shutdown
|
// Try using the PATH to find shutdown
|
||||||
try {
|
try {
|
||||||
console.log('Shutdown command not found in common paths, trying via PATH...');
|
logger.log('Shutdown command not found in common paths, trying via PATH...');
|
||||||
const { stdout } = await execAsync(`shutdown -h +${shutdownDelayMinutes} "UPS battery critical, shutting down in ${shutdownDelayMinutes} minutes"`, {
|
const { stdout } = await execAsync(`shutdown -h +${shutdownDelayMinutes} "UPS battery critical, shutting down in ${shutdownDelayMinutes} minutes"`, {
|
||||||
env: process.env // Pass the current environment
|
env: process.env // Pass the current environment
|
||||||
});
|
});
|
||||||
console.log('Shutdown initiated:', stdout);
|
logger.log(`Shutdown initiated: ${stdout}`);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new Error(`Shutdown command not found: ${e.message}`);
|
throw new Error(`Shutdown command not found: ${e.message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Monitor UPS during shutdown and force immediate shutdown if battery gets too low
|
// Monitor UPS during shutdown and force immediate shutdown if battery gets too low
|
||||||
console.log('Monitoring UPS during shutdown process...');
|
logger.log('Monitoring UPS during shutdown process...');
|
||||||
await this.monitorDuringShutdown();
|
await this.monitorDuringShutdown();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to initiate shutdown:', error);
|
logger.error(`Failed to initiate shutdown: ${error}`);
|
||||||
|
|
||||||
// Try alternative shutdown methods
|
// Try alternative shutdown methods
|
||||||
const alternatives = [
|
const alternatives = [
|
||||||
@ -376,24 +381,24 @@ export class NupstDaemon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (cmdPath) {
|
if (cmdPath) {
|
||||||
console.log(`Trying alternative shutdown method: ${cmdPath} ${alt.args.join(' ')}`);
|
logger.log(`Trying alternative shutdown method: ${cmdPath} ${alt.args.join(' ')}`);
|
||||||
await execFileAsync(cmdPath, alt.args);
|
await execFileAsync(cmdPath, alt.args);
|
||||||
return; // Exit if successful
|
return; // Exit if successful
|
||||||
} else {
|
} else {
|
||||||
// Try using PATH environment
|
// Try using PATH environment
|
||||||
console.log(`Trying alternative via PATH: ${alt.cmd} ${alt.args.join(' ')}`);
|
logger.log(`Trying alternative via PATH: ${alt.cmd} ${alt.args.join(' ')}`);
|
||||||
await execAsync(`${alt.cmd} ${alt.args.join(' ')}`, {
|
await execAsync(`${alt.cmd} ${alt.args.join(' ')}`, {
|
||||||
env: process.env // Pass the current environment
|
env: process.env // Pass the current environment
|
||||||
});
|
});
|
||||||
return; // Exit if successful
|
return; // Exit if successful
|
||||||
}
|
}
|
||||||
} catch (altError) {
|
} catch (altError) {
|
||||||
console.error(`Alternative method ${alt.cmd} failed:`, altError);
|
logger.error(`Alternative method ${alt.cmd} failed: ${altError}`);
|
||||||
// Continue to next method
|
// Continue to next method
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.error('All shutdown methods failed');
|
logger.error('All shutdown methods failed');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
import { NupstCli } from './cli.js';
|
import { NupstCli } from './cli.js';
|
||||||
|
import { logger } from './logger.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main entry point for NUPST
|
* Main entry point for NUPST
|
||||||
@ -13,6 +14,6 @@ async function main() {
|
|||||||
|
|
||||||
// Run the main function and handle any errors
|
// Run the main function and handle any errors
|
||||||
main().catch(error => {
|
main().catch(error => {
|
||||||
console.error('Error:', error);
|
logger.error(`Error: ${error}`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
|
147
ts/logger.ts
Normal file
147
ts/logger.ts
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
/**
|
||||||
|
* A simple logger class that provides consistent formatting for log messages
|
||||||
|
* including support for logboxes with title, lines, and closing
|
||||||
|
*/
|
||||||
|
export class Logger {
|
||||||
|
private currentBoxWidth: number | null = null;
|
||||||
|
private static instance: Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new Logger instance
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
this.currentBoxWidth = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the singleton logger instance
|
||||||
|
* @returns The singleton logger instance
|
||||||
|
*/
|
||||||
|
public static getInstance(): Logger {
|
||||||
|
if (!Logger.instance) {
|
||||||
|
Logger.instance = new Logger();
|
||||||
|
}
|
||||||
|
return Logger.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log a message
|
||||||
|
* @param message Message to log
|
||||||
|
*/
|
||||||
|
public log(message: string): void {
|
||||||
|
console.log(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log an error message
|
||||||
|
* @param message Error message to log
|
||||||
|
*/
|
||||||
|
public error(message: string): void {
|
||||||
|
console.error(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log a warning message with a warning emoji
|
||||||
|
* @param message Warning message to log
|
||||||
|
*/
|
||||||
|
public warn(message: string): void {
|
||||||
|
console.warn(`⚠️ ${message}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log a success message with a checkmark
|
||||||
|
* @param message Success message to log
|
||||||
|
*/
|
||||||
|
public success(message: string): void {
|
||||||
|
console.log(`✓ ${message}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log a logbox title and set the current box width
|
||||||
|
* @param title Title of the logbox
|
||||||
|
* @param width Width of the logbox (including borders)
|
||||||
|
*/
|
||||||
|
public logBoxTitle(title: string, width: number): void {
|
||||||
|
this.currentBoxWidth = width;
|
||||||
|
|
||||||
|
// Create the title line with appropriate padding
|
||||||
|
const paddedTitle = ` ${title} `;
|
||||||
|
const remainingSpace = width - 3 - paddedTitle.length;
|
||||||
|
|
||||||
|
// Title line: ┌─ Title ───┐
|
||||||
|
const titleLine = `┌─${paddedTitle}${'─'.repeat(remainingSpace)}┐`;
|
||||||
|
|
||||||
|
console.log(titleLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log a logbox line
|
||||||
|
* @param content Content of the line
|
||||||
|
* @param width Optional width override. If not provided, uses the current box width.
|
||||||
|
*/
|
||||||
|
public logBoxLine(content: string, width?: number): void {
|
||||||
|
const boxWidth = width || this.currentBoxWidth;
|
||||||
|
|
||||||
|
if (!boxWidth) {
|
||||||
|
throw new Error('No box width specified and no previous box width to use');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the available space for content
|
||||||
|
const availableSpace = boxWidth - 2; // Account for left and right borders
|
||||||
|
|
||||||
|
if (content.length <= availableSpace - 1) {
|
||||||
|
// If content fits with at least one space for the right border stripe
|
||||||
|
const padding = availableSpace - content.length - 1;
|
||||||
|
console.log(`│ ${content}${' '.repeat(padding)}│`);
|
||||||
|
} else {
|
||||||
|
// Content is too long, let it flow out of boundaries.
|
||||||
|
console.log(`│ ${content}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log a logbox end
|
||||||
|
* @param width Optional width override. If not provided, uses the current box width.
|
||||||
|
*/
|
||||||
|
public logBoxEnd(width?: number): void {
|
||||||
|
const boxWidth = width || this.currentBoxWidth;
|
||||||
|
|
||||||
|
if (!boxWidth) {
|
||||||
|
throw new Error('No box width specified and no previous box width to use');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the bottom border: └────────┘
|
||||||
|
console.log(`└${'─'.repeat(boxWidth - 2)}┘`);
|
||||||
|
|
||||||
|
// Reset the current box width
|
||||||
|
this.currentBoxWidth = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log a complete logbox with title, content lines, and ending
|
||||||
|
* @param title Title of the logbox
|
||||||
|
* @param lines Array of content lines
|
||||||
|
* @param width Width of the logbox
|
||||||
|
*/
|
||||||
|
public logBox(title: string, lines: string[], width: number): void {
|
||||||
|
this.logBoxTitle(title, width);
|
||||||
|
|
||||||
|
for (const line of lines) {
|
||||||
|
this.logBoxLine(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logBoxEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log a divider line
|
||||||
|
* @param width Width of the divider
|
||||||
|
* @param character Character to use for the divider (default: ─)
|
||||||
|
*/
|
||||||
|
public logDivider(width: number, character: string = '─'): void {
|
||||||
|
console.log(character.repeat(width));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Export a singleton instance for easy use
|
||||||
|
export const logger = Logger.getInstance();
|
32
ts/nupst.ts
32
ts/nupst.ts
@ -4,6 +4,7 @@ import { NupstSystemd } from './systemd.js';
|
|||||||
import { commitinfo } from './00_commitinfo_data.js';
|
import { commitinfo } from './00_commitinfo_data.js';
|
||||||
import { spawn } from 'child_process';
|
import { spawn } from 'child_process';
|
||||||
import * as https from 'https';
|
import * as https from 'https';
|
||||||
|
import { logger } from './logger.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main Nupst class that coordinates all components
|
* Main Nupst class that coordinates all components
|
||||||
@ -70,7 +71,7 @@ export class Nupst {
|
|||||||
|
|
||||||
return this.updateAvailable;
|
return this.updateAvailable;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error checking for updates: ${error.message}`);
|
logger.error(`Error checking for updates: ${error.message}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -162,28 +163,33 @@ export class Nupst {
|
|||||||
*/
|
*/
|
||||||
public logVersionInfo(checkForUpdates: boolean = true): void {
|
public logVersionInfo(checkForUpdates: boolean = true): void {
|
||||||
const version = this.getVersion();
|
const version = this.getVersion();
|
||||||
console.log('┌─ NUPST Version ────────────────────────────┐');
|
const boxWidth = 45;
|
||||||
console.log(`│ Current Version: ${version}`);
|
|
||||||
|
logger.logBoxTitle('NUPST Version', boxWidth);
|
||||||
|
logger.logBoxLine(`Current Version: ${version}`);
|
||||||
|
|
||||||
if (this.updateAvailable && this.latestVersion) {
|
if (this.updateAvailable && this.latestVersion) {
|
||||||
console.log(`│ Update Available: ${this.latestVersion}`);
|
logger.logBoxLine(`Update Available: ${this.latestVersion}`);
|
||||||
console.log('│ Run "sudo nupst update" to update');
|
logger.logBoxLine('Run "sudo nupst update" to update');
|
||||||
|
logger.logBoxEnd();
|
||||||
} else if (checkForUpdates) {
|
} else if (checkForUpdates) {
|
||||||
console.log('│ Checking for updates...');
|
logger.logBoxLine('Checking for updates...');
|
||||||
|
|
||||||
|
// We can't end the box yet since we're in an async operation
|
||||||
this.checkForUpdates().then(updateAvailable => {
|
this.checkForUpdates().then(updateAvailable => {
|
||||||
if (updateAvailable) {
|
if (updateAvailable) {
|
||||||
console.log(`│ Update Available: ${this.latestVersion}`);
|
logger.logBoxLine(`Update Available: ${this.latestVersion}`);
|
||||||
console.log('│ Run "sudo nupst update" to update');
|
logger.logBoxLine('Run "sudo nupst update" to update');
|
||||||
} else {
|
} else {
|
||||||
console.log('│ You are running the latest version');
|
logger.logBoxLine('You are running the latest version');
|
||||||
}
|
}
|
||||||
console.log('└──────────────────────────────────────────┘');
|
logger.logBoxEnd();
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
console.log('│ Could not check for updates');
|
logger.logBoxLine('Could not check for updates');
|
||||||
console.log('└──────────────────────────────────────────┘');
|
logger.logBoxEnd();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.log('└──────────────────────────────────────────┘');
|
logger.logBoxEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
108
ts/systemd.ts
108
ts/systemd.ts
@ -1,6 +1,7 @@
|
|||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import { execSync } from 'child_process';
|
import { execSync } from 'child_process';
|
||||||
import { NupstDaemon } from './daemon.js';
|
import { NupstDaemon } from './daemon.js';
|
||||||
|
import { logger } from './logger.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for managing systemd service
|
* Class for managing systemd service
|
||||||
@ -47,10 +48,11 @@ WantedBy=multi-user.target
|
|||||||
try {
|
try {
|
||||||
await fs.access(configPath);
|
await fs.access(configPath);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('┌─ Configuration Error ─────────────────────┐');
|
const boxWidth = 50;
|
||||||
console.error(`│ No configuration file found at ${configPath}`);
|
logger.logBoxTitle('Configuration Error', boxWidth);
|
||||||
console.error('│ Please run \'nupst setup\' first to create a configuration.');
|
logger.logBoxLine(`No configuration file found at ${configPath}`);
|
||||||
console.error('└──────────────────────────────────────────┘');
|
logger.logBoxLine("Please run 'nupst setup' first to create a configuration.");
|
||||||
|
logger.logBoxEnd();
|
||||||
throw new Error('Configuration not found');
|
throw new Error('Configuration not found');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -66,23 +68,24 @@ WantedBy=multi-user.target
|
|||||||
|
|
||||||
// Write the service file
|
// Write the service file
|
||||||
await fs.writeFile(this.serviceFilePath, this.serviceTemplate);
|
await fs.writeFile(this.serviceFilePath, this.serviceTemplate);
|
||||||
console.log('┌─ Service Installation ──────────────────────┐');
|
const boxWidth = 50;
|
||||||
console.log(`│ Service file created at ${this.serviceFilePath}`);
|
logger.logBoxTitle('Service Installation', boxWidth);
|
||||||
|
logger.logBoxLine(`Service file created at ${this.serviceFilePath}`);
|
||||||
|
|
||||||
// Reload systemd daemon
|
// Reload systemd daemon
|
||||||
execSync('systemctl daemon-reload');
|
execSync('systemctl daemon-reload');
|
||||||
console.log('│ Systemd daemon reloaded');
|
logger.logBoxLine('Systemd daemon reloaded');
|
||||||
|
|
||||||
// Enable the service
|
// Enable the service
|
||||||
execSync('systemctl enable nupst.service');
|
execSync('systemctl enable nupst.service');
|
||||||
console.log('│ Service enabled to start on boot');
|
logger.logBoxLine('Service enabled to start on boot');
|
||||||
console.log('└─────────────────────────────────────────────┘');
|
logger.logBoxEnd();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.message === 'Configuration not found') {
|
if (error.message === 'Configuration not found') {
|
||||||
// Just rethrow the error as the message has already been displayed
|
// Just rethrow the error as the message has already been displayed
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
console.error('Failed to install systemd service:', error);
|
logger.error(`Failed to install systemd service: ${error}`);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,15 +100,16 @@ WantedBy=multi-user.target
|
|||||||
await this.checkConfigExists();
|
await this.checkConfigExists();
|
||||||
|
|
||||||
execSync('systemctl start nupst.service');
|
execSync('systemctl start nupst.service');
|
||||||
console.log('┌─ Service Status ───────────────────────────┐');
|
const boxWidth = 45;
|
||||||
console.log('│ NUPST service started successfully');
|
logger.logBoxTitle('Service Status', boxWidth);
|
||||||
console.log('└────────────────────────────────────────────┘');
|
logger.logBoxLine('NUPST service started successfully');
|
||||||
|
logger.logBoxEnd();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.message === 'Configuration not found') {
|
if (error.message === 'Configuration not found') {
|
||||||
// Exit with error code since configuration is required
|
// Exit with error code since configuration is required
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
console.error('Failed to start service:', error);
|
logger.error(`Failed to start service: ${error}`);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -117,9 +121,9 @@ WantedBy=multi-user.target
|
|||||||
public async stop(): Promise<void> {
|
public async stop(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
execSync('systemctl stop nupst.service');
|
execSync('systemctl stop nupst.service');
|
||||||
console.log('NUPST service stopped');
|
logger.success('NUPST service stopped');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to stop service:', error);
|
logger.error(`Failed to stop service: ${error}`);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -132,9 +136,10 @@ WantedBy=multi-user.target
|
|||||||
try {
|
try {
|
||||||
// Enable debug mode if requested
|
// Enable debug mode if requested
|
||||||
if (debugMode) {
|
if (debugMode) {
|
||||||
console.log('┌─ Debug Mode ─────────────────────────────┐');
|
const boxWidth = 45;
|
||||||
console.log('│ SNMP debugging enabled - detailed logs will be shown');
|
logger.logBoxTitle('Debug Mode', boxWidth);
|
||||||
console.log('└──────────────────────────────────────────┘');
|
logger.logBoxLine('SNMP debugging enabled - detailed logs will be shown');
|
||||||
|
logger.logBoxEnd();
|
||||||
this.daemon.getNupstSnmp().enableDebug();
|
this.daemon.getNupstSnmp().enableDebug();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,7 +157,7 @@ WantedBy=multi-user.target
|
|||||||
await this.displayServiceStatus();
|
await this.displayServiceStatus();
|
||||||
await this.displayUpsStatus();
|
await this.displayUpsStatus();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Failed to get status: ${error.message}`);
|
logger.error(`Failed to get status: ${error.message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,13 +168,18 @@ WantedBy=multi-user.target
|
|||||||
private async displayServiceStatus(): Promise<void> {
|
private async displayServiceStatus(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const serviceStatus = execSync('systemctl status nupst.service').toString();
|
const serviceStatus = execSync('systemctl status nupst.service').toString();
|
||||||
console.log('┌─ Service Status ─────────────────────────┐');
|
const boxWidth = 45;
|
||||||
console.log(serviceStatus.split('\n').map(line => `│ ${line}`).join('\n'));
|
logger.logBoxTitle('Service Status', boxWidth);
|
||||||
console.log('└──────────────────────────────────────────┘');
|
// Process each line of the status output
|
||||||
|
serviceStatus.split('\n').forEach(line => {
|
||||||
|
logger.logBoxLine(line);
|
||||||
|
});
|
||||||
|
logger.logBoxEnd();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('┌─ Service Status ─────────────────────────┐');
|
const boxWidth = 45;
|
||||||
console.error('│ Service is not running');
|
logger.logBoxTitle('Service Status', boxWidth);
|
||||||
console.error('└──────────────────────────────────────────┘');
|
logger.logBoxLine('Service is not running');
|
||||||
|
logger.logBoxEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,22 +200,24 @@ WantedBy=multi-user.target
|
|||||||
timeout: Math.min(config.snmp.timeout, 10000) // Use at most 10 seconds for status check
|
timeout: Math.min(config.snmp.timeout, 10000) // Use at most 10 seconds for status check
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('┌─ Connecting to UPS... ─────────────────────┐');
|
const boxWidth = 45;
|
||||||
console.log(`│ Host: ${config.snmp.host}:${config.snmp.port}`);
|
logger.logBoxTitle('Connecting to UPS...', boxWidth);
|
||||||
console.log(`│ UPS Model: ${config.snmp.upsModel || 'cyberpower'}`);
|
logger.logBoxLine(`Host: ${config.snmp.host}:${config.snmp.port}`);
|
||||||
console.log('└────────────────────────────────────────────┘');
|
logger.logBoxLine(`UPS Model: ${config.snmp.upsModel || 'cyberpower'}`);
|
||||||
|
logger.logBoxEnd();
|
||||||
|
|
||||||
const status = await snmp.getUpsStatus(snmpConfig);
|
const status = await snmp.getUpsStatus(snmpConfig);
|
||||||
|
|
||||||
console.log('┌─ UPS Status ─────────────────────────────┐');
|
logger.logBoxTitle('UPS Status', boxWidth);
|
||||||
console.log(`│ Power Status: ${status.powerStatus}`);
|
logger.logBoxLine(`Power Status: ${status.powerStatus}`);
|
||||||
console.log(`│ Battery Capacity: ${status.batteryCapacity}%`);
|
logger.logBoxLine(`Battery Capacity: ${status.batteryCapacity}%`);
|
||||||
console.log(`│ Runtime Remaining: ${status.batteryRuntime} minutes`);
|
logger.logBoxLine(`Runtime Remaining: ${status.batteryRuntime} minutes`);
|
||||||
console.log('└──────────────────────────────────────────┘');
|
logger.logBoxEnd();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('┌─ UPS Status ─────────────────────────────┐');
|
const boxWidth = 45;
|
||||||
console.error(`│ Failed to retrieve UPS status: ${error.message}`);
|
logger.logBoxTitle('UPS Status', boxWidth);
|
||||||
console.error('└──────────────────────────────────────────┘');
|
logger.logBoxLine(`Failed to retrieve UPS status: ${error.message}`);
|
||||||
|
logger.logBoxEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,10 +233,10 @@ WantedBy=multi-user.target
|
|||||||
|
|
||||||
// Reload systemd daemon
|
// Reload systemd daemon
|
||||||
execSync('systemctl daemon-reload');
|
execSync('systemctl daemon-reload');
|
||||||
console.log('Systemd daemon reloaded');
|
logger.log('Systemd daemon reloaded');
|
||||||
console.log('NUPST service has been successfully uninstalled');
|
logger.success('NUPST service has been successfully uninstalled');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to disable and uninstall service:', error);
|
logger.error(`Failed to disable and uninstall service: ${error}`);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -235,11 +247,11 @@ WantedBy=multi-user.target
|
|||||||
*/
|
*/
|
||||||
private async stopService(): Promise<void> {
|
private async stopService(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
console.log('Stopping NUPST service...');
|
logger.log('Stopping NUPST service...');
|
||||||
execSync('systemctl stop nupst.service');
|
execSync('systemctl stop nupst.service');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Service might not be running, that's okay
|
// Service might not be running, that's okay
|
||||||
console.log('Service was not running or could not be stopped');
|
logger.log('Service was not running or could not be stopped');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,10 +261,10 @@ WantedBy=multi-user.target
|
|||||||
*/
|
*/
|
||||||
private async disableService(): Promise<void> {
|
private async disableService(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
console.log('Disabling NUPST service...');
|
logger.log('Disabling NUPST service...');
|
||||||
execSync('systemctl disable nupst.service');
|
execSync('systemctl disable nupst.service');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('Service was not enabled or could not be disabled');
|
logger.log('Service was not enabled or could not be disabled');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,11 +274,11 @@ WantedBy=multi-user.target
|
|||||||
*/
|
*/
|
||||||
private async removeServiceFile(): Promise<void> {
|
private async removeServiceFile(): Promise<void> {
|
||||||
if (await fs.stat(this.serviceFilePath).catch(() => null)) {
|
if (await fs.stat(this.serviceFilePath).catch(() => null)) {
|
||||||
console.log(`Removing service file ${this.serviceFilePath}...`);
|
logger.log(`Removing service file ${this.serviceFilePath}...`);
|
||||||
await fs.unlink(this.serviceFilePath);
|
await fs.unlink(this.serviceFilePath);
|
||||||
console.log('Service file removed');
|
logger.log('Service file removed');
|
||||||
} else {
|
} else {
|
||||||
console.log('Service file did not exist');
|
logger.log('Service file did not exist');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user