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:
@@ -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",
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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({
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -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',
|
||||||
|
|||||||
Reference in New Issue
Block a user