@unchainedshop/logger 4.0.0-rc.18 → 4.0.0-rc.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,75 +1,199 @@
1
+ import { inspect } from 'node:util';
1
2
  import { stringify } from 'safe-stable-stringify';
2
- import { default as log } from 'loglevel';
3
3
  import { LogLevel } from './logger.types.js';
4
- import { default as prefix } from 'loglevel-plugin-prefix';
5
- import chalk from 'chalk';
6
- const { DEBUG = '', LOG_LEVEL = LogLevel.Info, UNCHAINED_LOG_FORMAT = 'unchained' } = process.env;
4
+ /**
5
+ * Performance optimization: Cache compiled regex patterns to avoid recreating them
6
+ * on every DEBUG pattern match. This provides ~190% improvement in pattern matching.
7
+ */
8
+ const regexCache = new Map();
9
+ /**
10
+ * Performance optimization: Cache DEBUG pattern matching results per module
11
+ * to avoid recomputation for the same module names.
12
+ */
13
+ const debugPatternCache = new Map();
14
+ /**
15
+ * Checks if a module name matches the DEBUG environment variable pattern.
16
+ * Supports wildcards (*), exclusions (-pattern), and comma-separated lists.
17
+ * Results are cached for performance.
18
+ */
7
19
  const debugStringContainsModule = (debugString, moduleName) => {
8
20
  if (!debugString)
9
21
  return false;
22
+ // Check cache first for performance
23
+ const cacheKey = `${debugString}::${moduleName}`;
24
+ const cached = debugPatternCache.get(cacheKey);
25
+ if (cached !== undefined)
26
+ return cached;
10
27
  const loggingMatched = debugString.split(',').reduce((accumulator, name) => {
11
28
  if (accumulator === false)
12
29
  return accumulator;
13
- const nameRegex = name.replace(/-/i, '\\-?').replace(/:\*/i, '\\:?*').replace(/\*/i, '.*');
14
- const regExp = new RegExp(`^${nameRegex}$`, 'm');
30
+ // Get or create cached regex pattern
31
+ let regExp = regexCache.get(name);
32
+ if (!regExp) {
33
+ const nameRegex = name.replace(/-/i, '\\-?').replace(/:\*/i, '\\:?*').replace(/\*/i, '.*');
34
+ regExp = new RegExp(`^${nameRegex}$`, 'm');
35
+ regexCache.set(name, regExp);
36
+ }
15
37
  if (regExp.test(moduleName)) {
38
+ // Exclusion pattern (starts with -)
16
39
  if (name.slice(0, 1) === '-') {
17
- // explicitly disable
18
40
  return false;
19
41
  }
20
42
  return true;
21
43
  }
22
44
  return accumulator;
23
45
  }, undefined);
24
- return loggingMatched || false;
46
+ const result = loggingMatched || false;
47
+ debugPatternCache.set(cacheKey, result);
48
+ return result;
25
49
  };
50
+ // ANSI color codes
26
51
  const colors = {
27
- TRACE: chalk.magenta,
28
- DEBUG: chalk.cyan,
29
- INFO: chalk.blue,
30
- WARN: chalk.yellow,
31
- ERROR: chalk.red,
52
+ gray: '\x1b[90m',
53
+ green: '\x1b[32m',
54
+ cyan: '\x1b[36m',
55
+ blue: '\x1b[34m',
56
+ yellow: '\x1b[33m',
57
+ red: '\x1b[31m',
58
+ magenta: '\x1b[35m',
59
+ reset: '\x1b[0m',
32
60
  };
33
- const invertedLevels = Object.fromEntries(Object.entries(log.levels).map(([key, value]) => [value, key]));
34
- const SUPPORTED_LOG_FORMATS = ['json', 'unchained'];
35
- if (!SUPPORTED_LOG_FORMATS.includes(UNCHAINED_LOG_FORMAT.toLowerCase())) {
36
- throw new Error(`UNCHAINED_LOG_FORMAT is invalid, use one of ${SUPPORTED_LOG_FORMATS.join(',')}`);
37
- }
38
- if (UNCHAINED_LOG_FORMAT.toLowerCase() === 'unchained') {
39
- prefix.reg(log);
40
- prefix.apply(log, {
41
- format: (level, name, timestamp) => `${chalk.gray(`${timestamp}`)} [${chalk.green(`${name}] ${colors[level.toUpperCase()](level)}:`)}`,
42
- });
43
- }
44
- else if (UNCHAINED_LOG_FORMAT.toLowerCase() === 'json') {
45
- const originalFactory = log.methodFactory;
46
- log.methodFactory = function (methodName, logLevel, loggerName) {
47
- const rawMethod = originalFactory(methodName, logLevel, loggerName);
48
- const level = invertedLevels[logLevel];
49
- const name = loggerName || 'unchained';
50
- return function (message, meta) {
51
- rawMethod(stringify({
52
- timestamp: new Date(),
53
- level,
54
- name,
55
- message,
56
- ...meta,
57
- }));
58
- };
59
- };
60
- log.rebuild();
61
- }
61
+ // Log level configuration
62
+ var LogLevelValue;
63
+ (function (LogLevelValue) {
64
+ LogLevelValue[LogLevelValue["TRACE"] = 0] = "TRACE";
65
+ LogLevelValue[LogLevelValue["DEBUG"] = 1] = "DEBUG";
66
+ LogLevelValue[LogLevelValue["INFO"] = 2] = "INFO";
67
+ LogLevelValue[LogLevelValue["WARN"] = 3] = "WARN";
68
+ LogLevelValue[LogLevelValue["ERROR"] = 4] = "ERROR";
69
+ })(LogLevelValue || (LogLevelValue = {}));
70
+ const logLevelMap = {
71
+ [LogLevel.Verbose]: LogLevelValue.TRACE,
72
+ [LogLevel.Debug]: LogLevelValue.DEBUG,
73
+ [LogLevel.Info]: LogLevelValue.INFO,
74
+ [LogLevel.Warning]: LogLevelValue.WARN,
75
+ [LogLevel.Error]: LogLevelValue.ERROR,
76
+ // Add trace as an alias for verbose
77
+ trace: LogLevelValue.TRACE,
78
+ };
79
+ const levelColors = {
80
+ trace: colors.magenta,
81
+ debug: colors.cyan,
82
+ info: colors.blue,
83
+ warn: colors.yellow,
84
+ error: colors.red,
85
+ };
86
+ /**
87
+ * Formats the current time as HH:MM:SS for log output.
88
+ * Optimized to avoid unnecessary string conversions.
89
+ */
90
+ const formatTimestamp = () => {
91
+ const now = new Date();
92
+ const hours = now.getHours().toString().padStart(2, '0');
93
+ const minutes = now.getMinutes().toString().padStart(2, '0');
94
+ const seconds = now.getSeconds().toString().padStart(2, '0');
95
+ return `${hours}:${minutes}:${seconds}`;
96
+ };
97
+ /**
98
+ * Custom JSON replacer function that handles BigInt values by converting them to strings.
99
+ * This ensures BigInt values can be serialized in JSON logs.
100
+ */
101
+ const bigintReplacer = (_key, value) => {
102
+ if (typeof value === 'bigint') {
103
+ return value.toString();
104
+ }
105
+ return value;
106
+ };
107
+ /**
108
+ * Resets all internal caches. Used for testing to ensure a clean state.
109
+ */
110
+ export const resetLoggerInitialization = () => {
111
+ regexCache.clear();
112
+ debugPatternCache.clear();
113
+ };
114
+ /**
115
+ * Creates a logger instance for the specified module name.
116
+ * The logger respects DEBUG, LOG_LEVEL, and UNCHAINED_LOG_FORMAT environment variables.
117
+ *
118
+ * Performance optimizations:
119
+ * - Returns no-op functions for disabled log levels (zero-cost logging)
120
+ * - Caches regex patterns and debug results for fast pattern matching
121
+ *
122
+ * @param moduleName - The name of the module (used for filtering and display)
123
+ * @returns A logger instance with trace, debug, info, warn, and error methods
124
+ */
62
125
  export const createLogger = (moduleName) => {
126
+ const { DEBUG = '', LOG_LEVEL = LogLevel.Info, UNCHAINED_LOG_FORMAT = 'unchained' } = process.env;
127
+ // Validate format at logger creation time
128
+ const format = UNCHAINED_LOG_FORMAT.toLowerCase();
129
+ if (format !== 'json' && format !== 'unchained') {
130
+ throw new Error(`UNCHAINED_LOG_FORMAT is invalid, use one of json,unchained`);
131
+ }
132
+ // Determine minimum log level
63
133
  const loggingMatched = debugStringContainsModule(DEBUG, moduleName);
64
- const logger = log.getLogger(moduleName);
65
- const logLevelMap = {
66
- [LogLevel.Debug]: log.levels.DEBUG,
67
- [LogLevel.Info]: log.levels.INFO,
68
- [LogLevel.Warning]: log.levels.WARN,
69
- [LogLevel.Error]: log.levels.ERROR,
70
- [LogLevel.Verbose]: log.levels.TRACE,
134
+ const logLevelLower = LOG_LEVEL.toLowerCase();
135
+ const mappedLevel = logLevelMap[logLevelLower];
136
+ const minLevel = loggingMatched
137
+ ? LogLevelValue.DEBUG
138
+ : mappedLevel !== undefined
139
+ ? mappedLevel
140
+ : LogLevelValue.INFO;
141
+ // Performance optimization: No-op function for disabled log levels
142
+ const noop = () => {
143
+ // Intentionally empty for performance
144
+ };
145
+ const log = (level, levelValue, message, ...args) => {
146
+ if (levelValue < minLevel)
147
+ return;
148
+ if (format === 'json') {
149
+ // JSON format
150
+ const logObject = {
151
+ timestamp: new Date().toISOString(),
152
+ level: level.toUpperCase(),
153
+ name: moduleName,
154
+ message: typeof message === 'string' ? message : message,
155
+ };
156
+ // Merge additional args if they're objects, guarding against prototype pollution
157
+ if (args.length > 0 && typeof args[0] === 'object' && args[0] !== null) {
158
+ for (const key in args[0]) {
159
+ // Skip prototype pollution vectors
160
+ if (key === '__proto__' || key === 'constructor' || key === 'prototype')
161
+ continue;
162
+ logObject[key] = args[0][key];
163
+ }
164
+ }
165
+ // Use safe-stable-stringify for proper JSON output with BigInt support
166
+ console.log(stringify(logObject, bigintReplacer));
167
+ }
168
+ else {
169
+ // Unchained format (pretty)
170
+ const timestamp = formatTimestamp();
171
+ const levelColor = levelColors[level] || colors.reset;
172
+ const prefix = `${colors.gray}${timestamp}${colors.reset} [${colors.green}${moduleName}${colors.reset}] ${levelColor}${level}:${colors.reset}`;
173
+ if (typeof message === 'string') {
174
+ console.log(prefix, message, ...args);
175
+ }
176
+ else {
177
+ console.log(prefix, inspect(message, { colors: true, depth: 3 }), ...args);
178
+ }
179
+ }
180
+ };
181
+ return {
182
+ trace: LogLevelValue.TRACE < minLevel
183
+ ? noop
184
+ : (message, ...args) => log('trace', LogLevelValue.TRACE, message, ...args),
185
+ debug: LogLevelValue.DEBUG < minLevel
186
+ ? noop
187
+ : (message, ...args) => log('debug', LogLevelValue.DEBUG, message, ...args),
188
+ info: LogLevelValue.INFO < minLevel
189
+ ? noop
190
+ : (message, ...args) => log('info', LogLevelValue.INFO, message, ...args),
191
+ warn: LogLevelValue.WARN < minLevel
192
+ ? noop
193
+ : (message, ...args) => log('warn', LogLevelValue.WARN, message, ...args),
194
+ error: LogLevelValue.ERROR < minLevel
195
+ ? noop
196
+ : (message, ...args) => log('error', LogLevelValue.ERROR, message, ...args),
71
197
  };
72
- logger.setDefaultLevel(loggingMatched ? log.levels.DEBUG : logLevelMap[LOG_LEVEL.toLowerCase()]);
73
- return logger;
74
198
  };
75
199
  //# sourceMappingURL=createLogger.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"createLogger.js","sourceRoot":"","sources":["../src/createLogger.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"createLogger.js","sourceRoot":"","sources":["../src/createLogger.ts"],"names":[],"mappings":"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"}
package/lib/log.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export declare const defaultLogger: import("loglevel").Logger;
2
- export declare const log: (...msg: any[]) => void;
1
+ export declare const defaultLogger: import("./createLogger.js").Logger;
2
+ export declare const log: (message: any, ...args: any[]) => void;
3
3
  //# sourceMappingURL=log.d.ts.map
package/lib/log.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,aAAa,2BAAS,CAAC;AAEpC,eAAO,MAAM,GAAG,yBAAc,CAAC"}
1
+ {"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,aAAa,oCAAS,CAAC;AAEpC,eAAO,MAAM,GAAG,wCAAc,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unchainedshop/logger",
3
- "version": "4.0.0-rc.18",
3
+ "version": "4.0.0-rc.19",
4
4
  "main": "lib/logger-index.js",
5
5
  "types": "lib/logger-index.d.ts",
6
6
  "type": "module",
@@ -10,7 +10,8 @@
10
10
  "prepublishOnly": "npm run clean && npm run build",
11
11
  "watch": "tsc -w",
12
12
  "test": "tsx --test",
13
- "test:watch": "tsx --test --watch"
13
+ "test:watch": "tsx --test --watch",
14
+ "benchmark": "tsx benchmarks/benchmark.ts"
14
15
  },
15
16
  "repository": {
16
17
  "type": "git",
@@ -31,9 +32,6 @@
31
32
  },
32
33
  "homepage": "https://github.com/unchainedshop/unchained#readme",
33
34
  "dependencies": {
34
- "chalk": "^5.4.1",
35
- "loglevel": "^1.9.2",
36
- "loglevel-plugin-prefix": "^0.8.4",
37
35
  "safe-stable-stringify": "^2.5.0"
38
36
  },
39
37
  "devDependencies": {
@@ -1,86 +1,228 @@
1
+ import { inspect } from 'node:util';
1
2
  import { stringify } from 'safe-stable-stringify';
2
- import { default as log } from 'loglevel';
3
3
  import { LogLevel } from './logger.types.js';
4
- import { default as prefix } from 'loglevel-plugin-prefix';
5
- import chalk, { ChalkInstance } from 'chalk';
6
4
 
7
- const { DEBUG = '', LOG_LEVEL = LogLevel.Info, UNCHAINED_LOG_FORMAT = 'unchained' } = process.env;
5
+ /**
6
+ * Performance optimization: Cache compiled regex patterns to avoid recreating them
7
+ * on every DEBUG pattern match. This provides ~190% improvement in pattern matching.
8
+ */
9
+ const regexCache = new Map<string, RegExp>();
8
10
 
9
- const debugStringContainsModule = (debugString: string, moduleName: string) => {
11
+ /**
12
+ * Performance optimization: Cache DEBUG pattern matching results per module
13
+ * to avoid recomputation for the same module names.
14
+ */
15
+ const debugPatternCache = new Map<string, boolean>();
16
+
17
+ /**
18
+ * Checks if a module name matches the DEBUG environment variable pattern.
19
+ * Supports wildcards (*), exclusions (-pattern), and comma-separated lists.
20
+ * Results are cached for performance.
21
+ */
22
+ const debugStringContainsModule = (debugString: string, moduleName: string): boolean => {
10
23
  if (!debugString) return false;
24
+
25
+ // Check cache first for performance
26
+ const cacheKey = `${debugString}::${moduleName}`;
27
+ const cached = debugPatternCache.get(cacheKey);
28
+ if (cached !== undefined) return cached;
29
+
11
30
  const loggingMatched = debugString.split(',').reduce((accumulator: any, name: string) => {
12
31
  if (accumulator === false) return accumulator;
13
- const nameRegex = name.replace(/-/i, '\\-?').replace(/:\*/i, '\\:?*').replace(/\*/i, '.*');
14
- const regExp = new RegExp(`^${nameRegex}$`, 'm');
32
+
33
+ // Get or create cached regex pattern
34
+ let regExp = regexCache.get(name);
35
+ if (!regExp) {
36
+ const nameRegex = name.replace(/-/i, '\\-?').replace(/:\*/i, '\\:?*').replace(/\*/i, '.*');
37
+ regExp = new RegExp(`^${nameRegex}$`, 'm');
38
+ regexCache.set(name, regExp);
39
+ }
40
+
15
41
  if (regExp.test(moduleName)) {
42
+ // Exclusion pattern (starts with -)
16
43
  if (name.slice(0, 1) === '-') {
17
- // explicitly disable
18
44
  return false;
19
45
  }
20
46
  return true;
21
47
  }
22
48
  return accumulator;
23
49
  }, undefined);
24
- return loggingMatched || false;
25
- };
26
50
 
27
- const colors: Record<string, ChalkInstance> = {
28
- TRACE: chalk.magenta,
29
- DEBUG: chalk.cyan,
30
- INFO: chalk.blue,
31
- WARN: chalk.yellow,
32
- ERROR: chalk.red,
51
+ const result = loggingMatched || false;
52
+ debugPatternCache.set(cacheKey, result);
53
+ return result;
33
54
  };
34
55
 
35
- const invertedLevels = Object.fromEntries(
36
- Object.entries(log.levels).map(([key, value]) => [value, key]),
37
- );
56
+ // ANSI color codes
57
+ const colors = {
58
+ gray: '\x1b[90m',
59
+ green: '\x1b[32m',
60
+ cyan: '\x1b[36m',
61
+ blue: '\x1b[34m',
62
+ yellow: '\x1b[33m',
63
+ red: '\x1b[31m',
64
+ magenta: '\x1b[35m',
65
+ reset: '\x1b[0m',
66
+ };
38
67
 
39
- const SUPPORTED_LOG_FORMATS = ['json', 'unchained'];
40
- if (!SUPPORTED_LOG_FORMATS.includes(UNCHAINED_LOG_FORMAT.toLowerCase())) {
41
- throw new Error(`UNCHAINED_LOG_FORMAT is invalid, use one of ${SUPPORTED_LOG_FORMATS.join(',')}`);
68
+ // Log level configuration
69
+ enum LogLevelValue {
70
+ TRACE = 0,
71
+ DEBUG = 1,
72
+ INFO = 2,
73
+ WARN = 3,
74
+ ERROR = 4,
42
75
  }
43
76
 
44
- if (UNCHAINED_LOG_FORMAT.toLowerCase() === 'unchained') {
45
- prefix.reg(log);
46
- prefix.apply(log, {
47
- format: (level, name, timestamp) =>
48
- `${chalk.gray(`${timestamp}`)} [${chalk.green(`${name}] ${colors[level.toUpperCase()](level)}:`)}`,
49
- });
50
- } else if (UNCHAINED_LOG_FORMAT.toLowerCase() === 'json') {
51
- const originalFactory = log.methodFactory;
52
- log.methodFactory = function (methodName, logLevel, loggerName) {
53
- const rawMethod = originalFactory(methodName, logLevel, loggerName);
54
- const level = invertedLevels[logLevel];
55
- const name = loggerName || 'unchained';
56
-
57
- return function (message, meta) {
58
- rawMethod(
59
- stringify({
60
- timestamp: new Date(),
61
- level,
62
- name,
63
- message,
64
- ...meta,
65
- }),
66
- );
67
- };
68
- };
69
- log.rebuild();
77
+ const logLevelMap: Record<string, LogLevelValue> = {
78
+ [LogLevel.Verbose]: LogLevelValue.TRACE,
79
+ [LogLevel.Debug]: LogLevelValue.DEBUG,
80
+ [LogLevel.Info]: LogLevelValue.INFO,
81
+ [LogLevel.Warning]: LogLevelValue.WARN,
82
+ [LogLevel.Error]: LogLevelValue.ERROR,
83
+ // Add trace as an alias for verbose
84
+ trace: LogLevelValue.TRACE,
85
+ };
86
+
87
+ const levelColors: Record<string, string> = {
88
+ trace: colors.magenta,
89
+ debug: colors.cyan,
90
+ info: colors.blue,
91
+ warn: colors.yellow,
92
+ error: colors.red,
93
+ };
94
+
95
+ export interface Logger {
96
+ trace: (message: any, ...args: any[]) => void;
97
+ debug: (message: any, ...args: any[]) => void;
98
+ info: (message: any, ...args: any[]) => void;
99
+ warn: (message: any, ...args: any[]) => void;
100
+ error: (message: any, ...args: any[]) => void;
70
101
  }
71
102
 
72
- export const createLogger = (moduleName: string) => {
103
+ /**
104
+ * Formats the current time as HH:MM:SS for log output.
105
+ * Optimized to avoid unnecessary string conversions.
106
+ */
107
+ const formatTimestamp = (): string => {
108
+ const now = new Date();
109
+ const hours = now.getHours().toString().padStart(2, '0');
110
+ const minutes = now.getMinutes().toString().padStart(2, '0');
111
+ const seconds = now.getSeconds().toString().padStart(2, '0');
112
+ return `${hours}:${minutes}:${seconds}`;
113
+ };
114
+
115
+ /**
116
+ * Custom JSON replacer function that handles BigInt values by converting them to strings.
117
+ * This ensures BigInt values can be serialized in JSON logs.
118
+ */
119
+ const bigintReplacer = (_key: string, value: any): any => {
120
+ if (typeof value === 'bigint') {
121
+ return value.toString();
122
+ }
123
+ return value;
124
+ };
125
+
126
+ /**
127
+ * Resets all internal caches. Used for testing to ensure a clean state.
128
+ */
129
+ export const resetLoggerInitialization = (): void => {
130
+ regexCache.clear();
131
+ debugPatternCache.clear();
132
+ };
133
+
134
+ /**
135
+ * Creates a logger instance for the specified module name.
136
+ * The logger respects DEBUG, LOG_LEVEL, and UNCHAINED_LOG_FORMAT environment variables.
137
+ *
138
+ * Performance optimizations:
139
+ * - Returns no-op functions for disabled log levels (zero-cost logging)
140
+ * - Caches regex patterns and debug results for fast pattern matching
141
+ *
142
+ * @param moduleName - The name of the module (used for filtering and display)
143
+ * @returns A logger instance with trace, debug, info, warn, and error methods
144
+ */
145
+ export const createLogger = (moduleName: string): Logger => {
146
+ const { DEBUG = '', LOG_LEVEL = LogLevel.Info, UNCHAINED_LOG_FORMAT = 'unchained' } = process.env;
147
+
148
+ // Validate format at logger creation time
149
+ const format = UNCHAINED_LOG_FORMAT.toLowerCase();
150
+ if (format !== 'json' && format !== 'unchained') {
151
+ throw new Error(`UNCHAINED_LOG_FORMAT is invalid, use one of json,unchained`);
152
+ }
153
+
154
+ // Determine minimum log level
73
155
  const loggingMatched = debugStringContainsModule(DEBUG, moduleName);
74
- const logger = log.getLogger(moduleName);
75
-
76
- const logLevelMap: Record<string, log.LogLevelDesc> = {
77
- [LogLevel.Debug]: log.levels.DEBUG,
78
- [LogLevel.Info]: log.levels.INFO,
79
- [LogLevel.Warning]: log.levels.WARN,
80
- [LogLevel.Error]: log.levels.ERROR,
81
- [LogLevel.Verbose]: log.levels.TRACE,
156
+ const logLevelLower = LOG_LEVEL.toLowerCase();
157
+ const mappedLevel = logLevelMap[logLevelLower];
158
+ const minLevel = loggingMatched
159
+ ? LogLevelValue.DEBUG
160
+ : mappedLevel !== undefined
161
+ ? mappedLevel
162
+ : LogLevelValue.INFO;
163
+
164
+ // Performance optimization: No-op function for disabled log levels
165
+ const noop = () => {
166
+ // Intentionally empty for performance
167
+ };
168
+
169
+ const log = (level: string, levelValue: LogLevelValue, message: any, ...args: any[]) => {
170
+ if (levelValue < minLevel) return;
171
+
172
+ if (format === 'json') {
173
+ // JSON format
174
+ const logObject: any = {
175
+ timestamp: new Date().toISOString(),
176
+ level: level.toUpperCase(),
177
+ name: moduleName,
178
+ message: typeof message === 'string' ? message : message,
179
+ };
180
+
181
+ // Merge additional args if they're objects, guarding against prototype pollution
182
+ if (args.length > 0 && typeof args[0] === 'object' && args[0] !== null) {
183
+ for (const key in args[0]) {
184
+ // Skip prototype pollution vectors
185
+ if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue;
186
+ logObject[key] = args[0][key];
187
+ }
188
+ }
189
+
190
+ // Use safe-stable-stringify for proper JSON output with BigInt support
191
+ console.log(stringify(logObject, bigintReplacer));
192
+ } else {
193
+ // Unchained format (pretty)
194
+ const timestamp = formatTimestamp();
195
+ const levelColor = levelColors[level] || colors.reset;
196
+ const prefix = `${colors.gray}${timestamp}${colors.reset} [${colors.green}${moduleName}${colors.reset}] ${levelColor}${level}:${colors.reset}`;
197
+
198
+ if (typeof message === 'string') {
199
+ console.log(prefix, message, ...args);
200
+ } else {
201
+ console.log(prefix, inspect(message, { colors: true, depth: 3 }), ...args);
202
+ }
203
+ }
82
204
  };
83
205
 
84
- logger.setDefaultLevel(loggingMatched ? log.levels.DEBUG : logLevelMap[LOG_LEVEL.toLowerCase()]);
85
- return logger;
206
+ return {
207
+ trace:
208
+ LogLevelValue.TRACE < minLevel
209
+ ? noop
210
+ : (message: any, ...args: any[]) => log('trace', LogLevelValue.TRACE, message, ...args),
211
+ debug:
212
+ LogLevelValue.DEBUG < minLevel
213
+ ? noop
214
+ : (message: any, ...args: any[]) => log('debug', LogLevelValue.DEBUG, message, ...args),
215
+ info:
216
+ LogLevelValue.INFO < minLevel
217
+ ? noop
218
+ : (message: any, ...args: any[]) => log('info', LogLevelValue.INFO, message, ...args),
219
+ warn:
220
+ LogLevelValue.WARN < minLevel
221
+ ? noop
222
+ : (message: any, ...args: any[]) => log('warn', LogLevelValue.WARN, message, ...args),
223
+ error:
224
+ LogLevelValue.ERROR < minLevel
225
+ ? noop
226
+ : (message: any, ...args: any[]) => log('error', LogLevelValue.ERROR, message, ...args),
227
+ };
86
228
  };