- Updated .gitignore to exclude generated files and database - Modified package.json to change dev script and add new dependencies - Removed src/index.ts and created app.ts for Elysia server initialization - Added environment variable configuration in config/env.ts - Implemented MQTT adapter in adapter/mqtt.ts for message handling - Created Prisma client in prisma/client.ts and defined schema in prisma/schema.prisma - Added seeding script in prisma/seed.ts for measurement points - Established logging utility in utils/logger.ts for structured logging - Created bed router in routes/bed.ts for handling bed-related routes
83 lines
2.3 KiB
TypeScript
83 lines
2.3 KiB
TypeScript
import { createLogger, format, transports, Logger, LeveledLogMethod } from 'winston';
|
|
import * as fs from 'fs';
|
|
import * as path from 'path';
|
|
|
|
// Define log directory
|
|
const LOG_DIR = path.join(process.cwd(), 'logs');
|
|
|
|
// Ensure log directory exists
|
|
if (!fs.existsSync(LOG_DIR)) {
|
|
fs.mkdirSync(LOG_DIR, { recursive: true });
|
|
}
|
|
|
|
// Interface for topic logger options
|
|
interface TopicLoggerOptions {
|
|
topic: string;
|
|
level?: string;
|
|
}
|
|
|
|
// Create the base logger
|
|
const createBaseLogger = (level: string = 'debug') => {
|
|
return createLogger({
|
|
level,
|
|
format: format.combine(
|
|
format.timestamp(),
|
|
format.json()
|
|
),
|
|
transports: [
|
|
new transports.Console({
|
|
format: format.combine(
|
|
format.colorize(),
|
|
format.printf(({ timestamp, level, message, topic, ...meta }) => {
|
|
const topicStr = topic ? `[${topic}] ` : '';
|
|
return `${timestamp} ${level}: ${topicStr}${message} ${Object.keys(meta).length ? JSON.stringify(meta) : ''}`;
|
|
})
|
|
)
|
|
}),
|
|
new transports.File({
|
|
filename: path.join(LOG_DIR, 'combined.log')
|
|
})
|
|
]
|
|
});
|
|
};
|
|
|
|
// Main logger instance
|
|
const logger = createBaseLogger();
|
|
|
|
// Create a topic-specific logger
|
|
const createTopicLogger = (options: TopicLoggerOptions): Logger => {
|
|
const topicLogger = createBaseLogger(options.level);
|
|
|
|
// Create a wrapper that adds topic to all log messages
|
|
const wrappedLogger = {
|
|
...topicLogger,
|
|
};
|
|
|
|
// Wrap each log level method to include topic
|
|
(['error', 'warn', 'info', 'http', 'verbose', 'debug', 'silly'] as const).forEach((level) => {
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
wrappedLogger[level] = ((...args: any[]) => {
|
|
// Handle different call patterns
|
|
if (typeof args[0] === 'string') {
|
|
const message = args[0];
|
|
const meta = args[1] || {};
|
|
return topicLogger[level]({
|
|
message,
|
|
topic: options.topic,
|
|
...meta
|
|
});
|
|
} else {
|
|
// If first argument is an object, add topic to it
|
|
return topicLogger[level]({
|
|
...args[0],
|
|
topic: options.topic
|
|
});
|
|
}
|
|
}) as LeveledLogMethod;
|
|
});
|
|
|
|
return wrappedLogger as Logger;
|
|
};
|
|
|
|
export { logger, createTopicLogger };
|
|
export default logger;
|