chore: update dependencies and refactor import paths

- Updated package.json with latest dependency versions
- Added winston-daily-rotate-file type definitions
- Refactored import paths in tools and routes to use .js extensions
- Modified SSE routes to use getStatistics method
- Improved log rotation utility with more robust file cleanup
This commit is contained in:
jango-blockchained
2025-02-03 16:28:06 +01:00
parent 5362ed18ee
commit 5082f0d9fd
7 changed files with 52 additions and 35 deletions

View File

@@ -33,6 +33,7 @@
"helmet": "^7.1.0", "helmet": "^7.1.0",
"litemcp": "^0.7.0", "litemcp": "^0.7.0",
"uuid": "^9.0.1", "uuid": "^9.0.1",
"winston-daily-rotate-file": "^5.0.0",
"ws": "^8.16.0", "ws": "^8.16.0",
"zod": "^3.22.4" "zod": "^3.22.4"
}, },
@@ -46,11 +47,12 @@
"@types/node": "^20.17.16", "@types/node": "^20.17.16",
"@types/supertest": "^6.0.2", "@types/supertest": "^6.0.2",
"@types/uuid": "^9.0.8", "@types/uuid": "^9.0.8",
"@types/winston": "^2.4.4",
"@types/ws": "^8.5.10", "@types/ws": "^8.5.10",
"jest": "^29.7.0", "jest": "^29.7.0",
"node-fetch": "^3.3.2", "node-fetch": "^3.3.2",
"openai": "^4.82.0", "openai": "^4.82.0",
"rimraf": "^5.0.5", "rimraf": "^5.0.10",
"supertest": "^6.3.4", "supertest": "^6.3.4",
"ts-jest": "^29.1.2", "ts-jest": "^29.1.2",
"tsx": "^4.7.0", "tsx": "^4.7.0",

View File

@@ -4,7 +4,7 @@ import { middleware } from '../middleware/index.js';
import { sseManager } from '../sse/index.js'; import { sseManager } from '../sse/index.js';
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
import { TokenManager } from '../security/index.js'; import { TokenManager } from '../security/index.js';
import { tools } from '../services/tools.js'; import { tools } from '../tools/index.js';
import { Tool } from '../interfaces/index.js'; import { Tool } from '../interfaces/index.js';
const router = Router(); const router = Router();

View File

@@ -9,10 +9,10 @@
*/ */
import { Router } from 'express'; import { Router } from 'express';
import { mcpRoutes } from './mcp.routes'; import { mcpRoutes } from './mcp.routes.js';
import { sseRoutes } from './sse.routes'; import { sseRoutes } from './sse.routes.js';
import { toolRoutes } from './tool.routes'; import { toolRoutes } from './tool.routes.js';
import { healthRoutes } from './health.routes'; import { healthRoutes } from './health.routes.js';
/** /**
* Create main router instance * Create main router instance

View File

@@ -86,7 +86,7 @@ router.get('/subscribe', (req, res) => {
// Get SSE stats endpoint // Get SSE stats endpoint
router.get('/stats', async (req, res) => { router.get('/stats', async (req, res) => {
try { try {
const stats = await sseManager.getStats(); const stats = await sseManager.getStatistics();
res.json(stats); res.json(stats);
} catch (error) { } catch (error) {
res.status(500).json({ res.status(500).json({

View File

@@ -1,15 +1,15 @@
import { Tool } from '../types/index'; import { Tool } from '../types/index.js';
import { listDevicesTool } from './list-devices.tool'; import { listDevicesTool } from './list-devices.tool.js';
import { controlTool } from './control.tool'; import { controlTool } from './control.tool.js';
import { historyTool } from './history.tool'; import { historyTool } from './history.tool.js';
import { sceneTool } from './scene.tool'; import { sceneTool } from './scene.tool.js';
import { notifyTool } from './notify.tool'; import { notifyTool } from './notify.tool.js';
import { automationTool } from './automation.tool'; import { automationTool } from './automation.tool.js';
import { addonTool } from './addon.tool'; import { addonTool } from './addon.tool.js';
import { packageTool } from './package.tool'; import { packageTool } from './package.tool.js';
import { automationConfigTool } from './automation-config.tool'; import { automationConfigTool } from './automation-config.tool.js';
import { subscribeEventsTool } from './subscribe-events.tool'; import { subscribeEventsTool } from './subscribe-events.tool.js';
import { getSSEStatsTool } from './sse-stats.tool'; import { getSSEStatsTool } from './sse-stats.tool.js';
// Tool category types // Tool category types
export enum ToolCategory { export enum ToolCategory {
@@ -36,7 +36,7 @@ interface ToolMetadata {
} }
// Array to track all tools // Array to track all tools
const tools: Tool[] = [ export const tools: Tool[] = [
listDevicesTool, listDevicesTool,
controlTool, controlTool,
historyTool, historyTool,

View File

@@ -9,9 +9,14 @@
import fs from 'fs/promises'; import fs from 'fs/promises';
import path from 'path'; import path from 'path';
import { glob } from 'glob'; import glob from 'glob';
import { logger } from './logger.js'; import { logger } from './logger.js';
import { APP_CONFIG } from '../config/app.config.js'; import { APP_CONFIG } from '../config/app.config.js';
import { unlink } from 'fs/promises';
import { join } from 'path';
import { promisify } from 'util';
const globPromise = promisify(glob);
/** /**
* Interface for log file information * Interface for log file information
@@ -68,7 +73,7 @@ const parseDuration = (duration: string): number => {
*/ */
const getLogFiles = async (): Promise<LogFileInfo[]> => { const getLogFiles = async (): Promise<LogFileInfo[]> => {
const logDir = APP_CONFIG.LOGGING.DIR; const logDir = APP_CONFIG.LOGGING.DIR;
const files = await glob('*.log*', { cwd: logDir }); const files = await globPromise('*.log*', { cwd: logDir });
const fileInfos: LogFileInfo[] = []; const fileInfos: LogFileInfo[] = [];
for (const file of files) { for (const file of files) {
@@ -92,22 +97,32 @@ const getLogFiles = async (): Promise<LogFileInfo[]> => {
/** /**
* Clean up old log files * Clean up old log files
*/ */
const cleanupOldLogs = async (): Promise<void> => { export async function cleanupOldLogs(logDir: string, maxDays: number): Promise<void> {
try { try {
const maxDays = parseDuration(APP_CONFIG.LOGGING.MAX_DAYS); const files = await new Promise<string[]>((resolve, reject) => {
const maxAge = Date.now() - (maxDays * 24 * 60 * 60 * 1000); glob('*.log*', { cwd: logDir }, (err, matches) => {
if (err) reject(err);
else resolve(matches);
});
});
const files = await getLogFiles(); const now = Date.now();
const oldFiles = files.filter(file => file.date.getTime() < maxAge); const maxAge = maxDays * 24 * 60 * 60 * 1000;
for (const file of oldFiles) { for (const file of files) {
await fs.unlink(file.path); const filePath = join(logDir, file);
logger.debug(`Deleted old log file: ${file.filename}`); const stats = await fs.stat(filePath);
const dateMatch = file.match(/\d{4}-\d{2}-\d{2}/);
if (dateMatch && stats.ctimeMs < now - maxAge) {
await unlink(filePath);
logger.debug(`Deleted old log file: ${file}`);
}
} }
} catch (error) { } catch (error) {
logger.error('Error cleaning up old logs:', error); logger.error('Error cleaning up old logs:', error);
} }
}; }
/** /**
* Check and rotate log files based on size * Check and rotate log files based on size
@@ -147,7 +162,7 @@ export const initLogRotation = (): void => {
}); });
// Initial cleanup // Initial cleanup
cleanupOldLogs().catch(error => { cleanupOldLogs(APP_CONFIG.LOGGING.DIR, parseDuration(APP_CONFIG.LOGGING.MAX_DAYS)).catch(error => {
logger.error('Error in initial log cleanup:', error); logger.error('Error in initial log cleanup:', error);
}); });

View File

@@ -8,7 +8,7 @@
*/ */
import winston from 'winston'; import winston from 'winston';
import 'winston-daily-rotate-file'; import DailyRotateFile from 'winston-daily-rotate-file';
import { APP_CONFIG } from '../config/app.config.js'; import { APP_CONFIG } from '../config/app.config.js';
/** /**
@@ -56,7 +56,7 @@ const format = winston.format.combine(
* Transport for daily rotating file * Transport for daily rotating file
* Configures how logs are rotated and stored * Configures how logs are rotated and stored
*/ */
const dailyRotateFileTransport = new winston.transports.DailyRotateFile({ const dailyRotateFileTransport = new DailyRotateFile({
filename: 'logs/%DATE%.log', filename: 'logs/%DATE%.log',
datePattern: 'YYYY-MM-DD', datePattern: 'YYYY-MM-DD',
zippedArchive: true, zippedArchive: true,
@@ -73,7 +73,7 @@ const dailyRotateFileTransport = new winston.transports.DailyRotateFile({
* Transport for error logs * Transport for error logs
* Stores error logs in a separate file * Stores error logs in a separate file
*/ */
const errorFileTransport = new winston.transports.DailyRotateFile({ const errorFileTransport = new DailyRotateFile({
filename: 'logs/error-%DATE%.log', filename: 'logs/error-%DATE%.log',
datePattern: 'YYYY-MM-DD', datePattern: 'YYYY-MM-DD',
level: 'error', level: 'error',