From d35ac3e73bbbccc127fc09093b46d8d63ae0083b Mon Sep 17 00:00:00 2001 From: PunGrumpy <108584943+PunGrumpy@users.noreply.github.com> Date: Sun, 7 Apr 2024 20:46:14 +0700 Subject: [PATCH] refactor(*): update logger functionally to support configurable IP logging 1. modified the logger functions in logger.ts to accept an options parameter, allowing for the configuration of IP logging , 2. move all files in types folder to types.ts --- src/index.ts | 4 +- src/logger.ts | 91 +++++++++------------------------- src/options.ts | 11 ---- src/types.ts | 60 ++++++++++++++++++++++ src/types/ColorMap.ts | 12 ----- src/types/HttpError.ts | 11 ---- src/types/Logger.ts | 40 --------------- src/types/RequestInfo.ts | 16 ------ src/types/Server.ts | 16 ------ src/types/StoreData.ts | 12 ----- src/utils/colorMapping.ts | 2 +- src/utils/path.ts | 2 +- src/utils/start.ts | 2 +- test/types/ColorMap.test.ts | 2 +- test/types/HttpError.test.ts | 2 +- test/types/Logger.test.ts | 4 +- test/types/RequestInfo.test.ts | 2 +- test/types/Server.test.ts | 2 +- test/types/StoreData.test.ts | 2 +- test/utils/path.test.ts | 2 +- test/utils/start.test.ts | 2 +- 21 files changed, 96 insertions(+), 201 deletions(-) delete mode 100644 src/options.ts create mode 100644 src/types.ts delete mode 100644 src/types/ColorMap.ts delete mode 100644 src/types/HttpError.ts delete mode 100644 src/types/Logger.ts delete mode 100644 src/types/RequestInfo.ts delete mode 100644 src/types/Server.ts delete mode 100644 src/types/StoreData.ts diff --git a/src/index.ts b/src/index.ts index 7eaa550..d6b8924 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,7 +2,7 @@ import Elysia from 'elysia' import { createLogger, handleHttpError } from './logger' import startString from './utils/start' import { Server } from 'bun' -import { Options } from './options' +import { Options } from './types' /** * Creates a logger. @@ -20,7 +20,7 @@ import { Options } from './options' * @returns {Elysia} The logger. */ export const logger = (options?: Options): Elysia => { - const log = createLogger() + const log = createLogger(options) const elysia = new Elysia({ name: 'Logixlysia' diff --git a/src/logger.ts b/src/logger.ts index 7d17946..bb0cbea 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -4,51 +4,26 @@ import methodString from './utils/method' import logString from './utils/log' import pathString from './utils/path' import statusString from './utils/status' -import { RequestInfo } from './types/RequestInfo' -import { LogData, LogLevel, Logger } from './types/Logger' -import { StoreData } from './types/StoreData' -import { HttpError } from './types/HttpError' +import { HttpError, RequestInfo } from './types' +import { LogLevel, LogData, Logger, StoreData, Options } from './types' -/** - * Asynchronously logs a message constructed from various log components. - * - * @async - * @param {LogLevel} level - The log level. - * @param {RequestInfo} request - The request information. - * @param {LogData} data - The log data. - * @param {StoreData} store - The store data. - * - * @returns {Promise} - */ async function log( level: LogLevel, request: RequestInfo, data: LogData, - store: StoreData + store: StoreData, + options?: Options ): Promise { - const logMessage = buildLogMessage(level, request, data, store) - try { - await writeToLogAsync(logMessage) - } catch (error) { - console.error('Error logging message:', error) - } + const logMessage = buildLogMessage(level, request, data, store, options) + console.log(logMessage) } -/** - * Builds the log message string from given parameters. - * - * @param {LogLevel} level - The log level. - * @param {RequestInfo} request - The request information. - * @param {LogData} data - The log data. - * @param {StoreData} store - The store data. - * - * @returns {string} - The constructed log message. - */ function buildLogMessage( level: LogLevel, request: RequestInfo, data: LogData, - store: StoreData + store: StoreData, + options?: Options ): string { const nowStr = chalk.bgYellow(chalk.black(new Date().toLocaleString())) const levelStr = logString(level) @@ -58,56 +33,36 @@ function buildLogMessage( const statusStr = statusString(data.status || 200) const messageStr = data.message || '' - return `🦊 ${nowStr} ${levelStr} ${durationStr} ${methodStr} ${pathnameStr} ${statusStr} ${messageStr}` -} + let logMessage = `🦊 ${nowStr} ${levelStr} ${durationStr} ${methodStr} ${pathnameStr} ${statusStr} ${messageStr}` -/** - * Writes a log message to the console asynchronously. - * - * @async - * @param {string} message - The message to log. - * - * @returns {Promise} - * @throws {Error} - If the timeout is reached. - */ -function writeToLogAsync(message: string): Promise { - return new Promise((resolve, reject) => { - console.log(message) - resolve() + if (options?.ip) { + const forwardedFor = request.headers.get('x-forwarded-for') + if (forwardedFor) { + logMessage += ` IP: ${forwardedFor}` + } + } - setTimeout(() => { - reject(new Error('Timed out while writing to log.')) - }) - }) + return logMessage } -/** - * Creates a logger instance with an asynchronous log method. - * - * @returns {Logger} - The logger instance. - */ -export const createLogger = (): Logger => ({ - log: (level, request, data, store) => log(level, request, data, store) +export const createLogger = (options?: Options): Logger => ({ + log: (level, request, data, store) => + log(level, request, data, store, options) }) -/** - * Handle HTTP errors and log them with the appropriate status code. - * - * @param {RequestInfo} request - The request information. - * @param {Error} error - The error object. - * @param {StoreData} store - The store data. - */ export const handleHttpError = ( request: RequestInfo, error: Error, - store: StoreData + store: StoreData, + options?: Options ): void => { const statusCode = error instanceof HttpError ? error.status : 500 const logMessage = buildLogMessage( 'ERROR', request, { status: statusCode }, - store + store, + options ) console.error(logMessage) } diff --git a/src/options.ts b/src/options.ts deleted file mode 100644 index 800f313..0000000 --- a/src/options.ts +++ /dev/null @@ -1,11 +0,0 @@ -/** - * Options for the logger. - */ -interface Options { - /** - * Whether to log the IP address of the client. - */ - ip?: boolean -} - -export { Options } diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..adc9b10 --- /dev/null +++ b/src/types.ts @@ -0,0 +1,60 @@ +interface RequestInfo { + headers: { get: (key: string) => any } + method: string + url: string +} + +interface Server { + hostname?: string + port?: number + protocol?: string +} + +interface ColorMap { + [key: string]: (str: string) => string +} + +type LogLevel = 'INFO' | 'WARNING' | 'ERROR' | string + +interface LogData { + status?: number + message?: string +} + +interface Logger { + log( + level: LogLevel, + request: RequestInfo, + data: LogData, + store: StoreData + ): void +} + +interface StoreData { + beforeTime: bigint +} + +class HttpError extends Error { + status: number + + constructor(status: number, message: string) { + super(message) + this.status = status + } +} + +interface Options { + ip?: boolean +} + +export { + RequestInfo, + Server, + ColorMap, + LogLevel, + LogData, + Logger, + StoreData, + HttpError, + Options +} diff --git a/src/types/ColorMap.ts b/src/types/ColorMap.ts deleted file mode 100644 index f4ed27e..0000000 --- a/src/types/ColorMap.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * The color map interface. - * - * @interface ColorMap - * - * @property {string} key The color function. - */ -interface ColorMap { - [key: string]: (str: string) => string -} - -export { ColorMap } diff --git a/src/types/HttpError.ts b/src/types/HttpError.ts deleted file mode 100644 index 4ea9684..0000000 --- a/src/types/HttpError.ts +++ /dev/null @@ -1,11 +0,0 @@ -/** - * Custom Error class for HTTP errors. - */ -export class HttpError extends Error { - status: number - - constructor(status: number, message: string) { - super(message) - this.status = status - } -} diff --git a/src/types/Logger.ts b/src/types/Logger.ts deleted file mode 100644 index b99f971..0000000 --- a/src/types/Logger.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { RequestInfo } from './RequestInfo' -import { StoreData } from './StoreData' - -/** - * The log level, including standard and custom levels. - * - * @type {string} - */ -type LogLevel = 'INFO' | 'WARNING' | 'ERROR' | string - -/** - * The log data interface. - * - * @interface LogData - * - * @property {number} status - The status code. - * @property {string} message - The message. - */ -interface LogData { - status?: number - message?: string -} - -/** - * The logger interface. - * - * @interface Logger - * - * @property {Function} log - Logs a message with a given log level. - */ -interface Logger { - log( - level: LogLevel, - request: RequestInfo, - data: LogData, - store: StoreData - ): void -} - -export { LogLevel, LogData, Logger } diff --git a/src/types/RequestInfo.ts b/src/types/RequestInfo.ts deleted file mode 100644 index de97e83..0000000 --- a/src/types/RequestInfo.ts +++ /dev/null @@ -1,16 +0,0 @@ -/** - * The request info. - * - * @interface RequestInfo - * - * @property {Object} headers The request headers. - * @property {string} method The request method. - * @property {string} url The request URL. - */ -interface RequestInfo { - headers: { get: (key: string) => any } - method: string - url: string -} - -export { RequestInfo } diff --git a/src/types/Server.ts b/src/types/Server.ts deleted file mode 100644 index f5f41cb..0000000 --- a/src/types/Server.ts +++ /dev/null @@ -1,16 +0,0 @@ -/** - * The server information. - * - * @interface Server - * - * @property {string} hostname The server hostname. - * @property {number} port The server port. - * @property {string} protocol The server protocol. - */ -interface Server { - hostname?: string - port?: number - protocol?: string -} - -export { Server } diff --git a/src/types/StoreData.ts b/src/types/StoreData.ts deleted file mode 100644 index f07f1d2..0000000 --- a/src/types/StoreData.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * The store data interface. - * - * @interface StoreData - * - * @property {bigint} beforeTime The time before the request. - */ -interface StoreData { - beforeTime: bigint -} - -export { StoreData } diff --git a/src/utils/colorMapping.ts b/src/utils/colorMapping.ts index 7d43fbb..712a756 100644 --- a/src/utils/colorMapping.ts +++ b/src/utils/colorMapping.ts @@ -1,5 +1,5 @@ import chalk from 'chalk' -import { ColorMap } from '~/types/ColorMap' +import { ColorMap } from '~/types' /** * The color map for the log levels. diff --git a/src/utils/path.ts b/src/utils/path.ts index 9f97747..488606a 100644 --- a/src/utils/path.ts +++ b/src/utils/path.ts @@ -1,4 +1,4 @@ -import { RequestInfo } from '~/types/RequestInfo' +import { RequestInfo } from '~/types' /** * Returns the path string. diff --git a/src/utils/start.ts b/src/utils/start.ts index 6db792a..dfd928b 100644 --- a/src/utils/start.ts +++ b/src/utils/start.ts @@ -1,4 +1,4 @@ -import { Server } from '~/types/Server' +import { Server } from '~/types' /** * Creates a box text. diff --git a/test/types/ColorMap.test.ts b/test/types/ColorMap.test.ts index 1f27e10..ee3769c 100644 --- a/test/types/ColorMap.test.ts +++ b/test/types/ColorMap.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'bun:test' -import { ColorMap } from '~/types/ColorMap' +import { ColorMap } from '~/types' describe('Color Mapping Interface', () => { it('Defines an object with string keys mapping to functions', () => { diff --git a/test/types/HttpError.test.ts b/test/types/HttpError.test.ts index cd5c7d1..0a82db6 100644 --- a/test/types/HttpError.test.ts +++ b/test/types/HttpError.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'bun:test' -import { HttpError } from '~/types/HttpError' +import { HttpError } from '~/types' describe('HttpError', () => { it('Should create an instance with correct status and message', () => { diff --git a/test/types/Logger.test.ts b/test/types/Logger.test.ts index 1a7725b..f9b707f 100644 --- a/test/types/Logger.test.ts +++ b/test/types/Logger.test.ts @@ -1,7 +1,5 @@ import { beforeEach, describe, expect, it, jest } from 'bun:test' -import { LogData } from '~/types/Logger' -import { RequestInfo } from '~/types/RequestInfo' -import { StoreData } from '~/types/StoreData' +import { RequestInfo, LogData, StoreData } from '~/types' interface Logger { info(request: RequestInfo, data: LogData, store: StoreData): void diff --git a/test/types/RequestInfo.test.ts b/test/types/RequestInfo.test.ts index 0959224..b1a103e 100644 --- a/test/types/RequestInfo.test.ts +++ b/test/types/RequestInfo.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'bun:test' -import { RequestInfo } from '~/types/RequestInfo' +import { RequestInfo } from '~/types' describe('Request Infomation interface', () => { it('Defines the RequestInfo interface correctly', () => { diff --git a/test/types/Server.test.ts b/test/types/Server.test.ts index 06ec754..94d76bc 100644 --- a/test/types/Server.test.ts +++ b/test/types/Server.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'bun:test' -import { Server } from '~/types/Server' +import { Server } from '~/types' describe('Server interface', () => { it('Defines the Server interface correctly', () => { diff --git a/test/types/StoreData.test.ts b/test/types/StoreData.test.ts index a21f264..8d845a3 100644 --- a/test/types/StoreData.test.ts +++ b/test/types/StoreData.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'bun:test' -import { StoreData } from '~/types/StoreData' +import { StoreData } from '~/types' describe('Store Data interface', () => { it('Defines the StoreData interface correctly', () => { diff --git a/test/utils/path.test.ts b/test/utils/path.test.ts index 679a45f..eef0afe 100644 --- a/test/utils/path.test.ts +++ b/test/utils/path.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'bun:test' -import { RequestInfo } from '~/types/RequestInfo' +import { RequestInfo } from '~/types' import pathString from '~/utils/path' describe('Path String', () => { diff --git a/test/utils/start.test.ts b/test/utils/start.test.ts index aebeb33..aaa337d 100644 --- a/test/utils/start.test.ts +++ b/test/utils/start.test.ts @@ -1,5 +1,5 @@ import { afterEach, beforeEach, describe, expect, it, jest } from 'bun:test' -import { Server } from '~/types/Server' +import { Server } from '~/types' import startString from '~/utils/start' describe('Start String', () => {