logxpert 2.0.0 → 2.1.0

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.
package/README.md CHANGED
@@ -1,6 +1,11 @@
1
1
  # LogXpert
2
2
 
3
- LogXpert is a powerful logging library for Node.js that provides easy-to-use logging methods with colorful formatted output and optional file logging support.
3
+ Colorful console logging for Node.js with optional daily file rotation.
4
+
5
+ - Zero heavy dependencies — built-in engine.
6
+ - Daily file rotation with retention, size limits and gzip.
7
+ - Per-level colors, lazy messages, child loggers, isolated instances.
8
+ - Works from JS and TS, CommonJS and ESM.
4
9
 
5
10
  ## Installation
6
11
 
@@ -8,90 +13,106 @@ LogXpert is a powerful logging library for Node.js that provides easy-to-use log
8
13
  npm install logxpert
9
14
  ```
10
15
 
11
- ## Usage
16
+ Requires Node.js `>=18`. Recommended minimum: Node.js 22 LTS. See [NODE_SUPPORT.md](NODE_SUPPORT.md) for the full support policy.
12
17
 
13
- CommonJS:
18
+ ## Quick start
14
19
 
15
20
  ```js
16
21
  const log = require('logxpert');
22
+ // or: import log from 'logxpert';
23
+
24
+ log('general message'); // shortcut for info
25
+ log.info('hello', { user: 1 }); // with metadata
26
+ log.error(new Error('boom')); // Errors print message + stack
27
+ log.debug(() => JSON.stringify(hugeObject)); // lazy: skipped if level disabled
28
+ ```
17
29
 
18
- log('general message');
19
- log.error('error message');
20
- log.warn('warn message');
21
- log.info('info with meta', { user: 1 });
22
- log.debug({ structured: 'object' });
23
- log.error(new Error('boom'));
30
+ Levels: `error → warn → info → http → verbose → debug → silly` (default `debug`).
31
+
32
+ ```js
33
+ log.setLevel('info'); // or via LOG_LEVEL env variable
24
34
  ```
25
35
 
26
- ESM:
36
+ ## File logging
27
37
 
28
38
  ```js
29
- import log from 'logxpert';
39
+ log.settings({ files: { folder: 'logs' } });
40
+ // → logs/logxpert-2026_10_08.log (prefix defaults to your package.json name)
41
+
42
+ log.settings({ files: { folder: 'logs', prefix: 'api' } });
43
+ // → logs/api-2026_10_08.log
30
44
 
31
- log.info('hello');
45
+ // Full control (omit prefix when used):
46
+ log.settings({ files: { folder: 'logs', filePattern: 'app-%datePattern%.log' } });
32
47
  ```
33
48
 
34
- Set level (`LOG_LEVEL` env also respected):
49
+ `%datePattern%` is replaced by the date (`datePattern` defaults to `YYYY_MM_DD`). Combining `prefix` with `filePattern` throws — pick one.
35
50
 
36
51
  ```js
37
- log.setLevel('info');
38
- console.log(log.getLevel());
52
+ log.settings({
53
+ files: {
54
+ folder: 'logs',
55
+ runNumber: true, // off by default → app-2026_10_08-1.log, -2.log, ...
56
+ maxFile: '14d', // retention
57
+ maxSize: '20m', // rotate above this size
58
+ zippedArchive: true,
59
+ },
60
+ });
61
+ log.close(); // call on shutdown
39
62
  ```
40
63
 
41
- Isolated instances and child loggers:
64
+ ## Console & instances
42
65
 
43
66
  ```js
67
+ log.settings({
68
+ console: {
69
+ enableTimestamp: true,
70
+ timestampFormat: 'YYYY-MM-DD HH:mm:ss',
71
+ colorize: true,
72
+ colors: { info: 'blue', error: false }, // names, ANSI 0-255, or false per level
73
+ },
74
+ });
75
+
76
+ // Default colors: error red, warn yellow, info green, http magenta,
77
+ // verbose cyan, debug blue, silly gray. Only the [level] tag is colored.
78
+
44
79
  const { createLogger } = require('logxpert');
45
- const apiLog = createLogger({ level: 'info' });
46
- apiLog.info('isolated');
80
+ const apiLog = createLogger({ level: 'info' }); // independent instance
47
81
 
48
- const child = log.child({ service: 'api' });
49
- child.info('child message');
82
+ const child = log.child({ service: 'api' }); // bound context
50
83
  ```
51
84
 
52
- ### File output & console timestamp
85
+ ## Full configuration (copy-paste)
53
86
 
54
87
  ```js
55
88
  log.settings({
56
- level: 'debug',
89
+ level: 'debug', // or process.env.LOG_LEVEL
57
90
  console: {
58
91
  enableTimestamp: true,
59
92
  timestampFormat: 'YYYY-MM-DD HH:mm:ss',
60
93
  timestampPrefix: '',
61
94
  timestampSuffix: '',
62
- colorize: true
95
+ colorize: true,
96
+ colors: { info: 'blue', warn: 208, error: false }
97
+ // enabled: false, // file-only logging: silence the console
63
98
  },
64
99
  files: {
65
100
  folder: 'logs',
66
- filename: 'application-%DATE%.log',
67
- filesName: 'YYYY-MM-DD',
101
+ prefix: undefined, // defaults to your package.json name
102
+ // filePattern: 'app-%datePattern%.log', // full control (omit prefix if used)
103
+ datePattern: 'YYYY_MM_DD',
104
+ runNumber: false, // or true, or { separator: '-', padding: 0, startAt: 1 }
68
105
  maxFile: '14d',
69
106
  maxSize: '20m',
70
- zippedArchive: false
107
+ zippedArchive: false,
71
108
  }
72
109
  });
73
110
  ```
74
111
 
75
- Close file transports on shutdown:
76
-
77
- ```js
78
- log.close();
79
- ```
80
-
81
- ## API Reference
82
-
83
- - **log(message, ...meta):** info level.
84
- - **log.error/warn/info/debug/http/verbose/silly(message, ...meta)**
85
- - **log.log(level, message, ...meta)**
86
- - **log.settings({ console, files, level })**
87
- - **log.setLevel(level) / log.getLevel()**
88
- - **log.createLogger(options):** independent instance.
89
- - **log.child(meta):** child logger with bound context.
90
- - **log.close():** remove file transport.
112
+ Legacy aliases: `appName` (= `prefix`), `filename`/`pattern` (= `filePattern`), `filesName`/`dateFormat` (= `datePattern`).
91
113
 
92
- Console options: `enableTimestamp`, `timestampFormat`, `timestampPrefix`, `timestampSuffix`, `colorize`, `level`.
93
- Files options: `folder`, `filename`, `filesName`/`datePattern`, `maxFile`/`maxFiles`, `maxSize`, `zippedArchive`, `level`.
114
+ Security: messages are stripped of ANSI escapes and control characters (except `\n`, `\t`); file patterns escaping the log folder (`..`, absolute paths) are rejected.
94
115
 
95
116
  ## License
96
117
 
97
- GPL-3.0-only. See [LICENSE](LICENSE).
118
+ Apache-2.0. See [LICENSE](LICENSE).
package/index.d.mts ADDED
@@ -0,0 +1,23 @@
1
+ import log from './index.js';
2
+
3
+ export default log;
4
+
5
+ export const settings: typeof log.settings;
6
+ export const setLevel: typeof log.setLevel;
7
+ export const getLevel: typeof log.getLevel;
8
+ export const child: typeof log.child;
9
+ export const close: typeof log.close;
10
+ export const createLogger: typeof log.createLogger;
11
+ export const error: typeof log.error;
12
+ export const warn: typeof log.warn;
13
+ export const info: typeof log.info;
14
+ export const debug: typeof log.debug;
15
+
16
+ export type LogLevel = log.LogLevel;
17
+ export type LevelColor = log.LevelColor;
18
+ export type ConsoleOptions = log.ConsoleOptions;
19
+ export type FilesOptions = log.FilesOptions;
20
+ export type RunNumberOptions = log.RunNumberOptions;
21
+ export type LogSettingsOptions = log.LogSettingsOptions;
22
+ export type ChildLogger = log.ChildLogger;
23
+ export type LogXpert = log.LogXpert;
package/index.d.ts CHANGED
@@ -1,57 +1,83 @@
1
- export type LogLevel = 'error' | 'warn' | 'info' | 'http' | 'verbose' | 'debug' | 'silly';
2
-
3
- export interface ConsoleOptions {
4
- enableTimestamp?: boolean;
5
- timestampFormat?: string;
6
- timestampPrefix?: string;
7
- timestampSuffix?: string;
8
- colorize?: boolean;
9
- level?: LogLevel;
10
- }
1
+ declare namespace log {
2
+ export type LogLevel = 'error' | 'warn' | 'info' | 'http' | 'verbose' | 'debug' | 'silly';
11
3
 
12
- export interface FilesOptions {
13
- folder?: string;
14
- filesName?: string;
15
- datePattern?: string;
16
- filename?: string;
17
- maxFile?: string;
18
- maxFiles?: string;
19
- maxSize?: string;
20
- zippedArchive?: boolean;
21
- level?: LogLevel;
22
- }
4
+ export type LevelColor = string | number | false | null;
23
5
 
24
- export interface LogSettingsOptions {
25
- console?: ConsoleOptions;
26
- files?: FilesOptions;
27
- level?: LogLevel;
28
- }
6
+ export interface ConsoleOptions {
7
+ enabled?: boolean;
8
+ enableTimestamp?: boolean;
9
+ timestampFormat?: string;
10
+ timestampPrefix?: string;
11
+ timestampSuffix?: string;
12
+ colorize?: boolean;
13
+ colors?: Partial<Record<LogLevel, LevelColor>>;
14
+ level?: LogLevel;
15
+ }
29
16
 
30
- export interface ChildLogger {
31
- error(message: unknown, ...meta: unknown[]): void;
32
- warn(message: unknown, ...meta: unknown[]): void;
33
- info(message: unknown, ...meta: unknown[]): void;
34
- debug(message: unknown, ...meta: unknown[]): void;
35
- log(level: LogLevel, message: unknown, ...meta: unknown[]): void;
36
- }
17
+ export interface RunNumberOptions {
18
+ enabled?: boolean;
19
+ separator?: string;
20
+ padding?: number;
21
+ startAt?: number;
22
+ }
37
23
 
38
- export interface LogXpert {
39
- (message: unknown, ...meta: unknown[]): void;
40
- error(message: unknown, ...meta: unknown[]): void;
41
- warn(message: unknown, ...meta: unknown[]): void;
42
- info(message: unknown, ...meta: unknown[]): void;
43
- debug(message: unknown, ...meta: unknown[]): void;
44
- http(message: unknown, ...meta: unknown[]): void;
45
- verbose(message: unknown, ...meta: unknown[]): void;
46
- silly(message: unknown, ...meta: unknown[]): void;
47
- log(level: LogLevel, message: unknown, ...meta: unknown[]): void;
48
- settings(options?: LogSettingsOptions): void;
49
- setLevel(level: LogLevel): void;
50
- getLevel(): string;
51
- child(meta?: Record<string, unknown>): ChildLogger;
52
- close(): void;
53
- createLogger(options?: LogSettingsOptions): LogXpert;
24
+ export interface FilesOptions {
25
+ folder?: string;
26
+ /** Preferred: date format for %DATE%. */
27
+ datePattern?: string;
28
+ /** @deprecated Use datePattern. */
29
+ filesName?: string;
30
+ dateFormat?: string;
31
+ /** Preferred: filename template containing %DATE%. */
32
+ filePattern?: string;
33
+ pattern?: string;
34
+ /** @deprecated Use filePattern. */
35
+ filename?: string;
36
+ /** Preferred: filename prefix used when no pattern is given. */
37
+ prefix?: string;
38
+ /** @deprecated Use prefix. */
39
+ appName?: string;
40
+ runNumber?: boolean | RunNumberOptions;
41
+ maxFile?: string;
42
+ maxFiles?: string;
43
+ maxSize?: string;
44
+ zippedArchive?: boolean;
45
+ level?: LogLevel;
46
+ }
47
+
48
+ export interface LogSettingsOptions {
49
+ console?: ConsoleOptions | false;
50
+ files?: FilesOptions;
51
+ level?: LogLevel;
52
+ }
53
+
54
+ export interface ChildLogger {
55
+ error(message: unknown, ...meta: unknown[]): void;
56
+ warn(message: unknown, ...meta: unknown[]): void;
57
+ info(message: unknown, ...meta: unknown[]): void;
58
+ debug(message: unknown, ...meta: unknown[]): void;
59
+ log(level: LogLevel, message: unknown, ...meta: unknown[]): void;
60
+ }
61
+
62
+ export interface LogXpert {
63
+ (message: unknown, ...meta: unknown[]): void;
64
+ error(message: unknown, ...meta: unknown[]): void;
65
+ warn(message: unknown, ...meta: unknown[]): void;
66
+ info(message: unknown, ...meta: unknown[]): void;
67
+ debug(message: unknown, ...meta: unknown[]): void;
68
+ http(message: unknown, ...meta: unknown[]): void;
69
+ verbose(message: unknown, ...meta: unknown[]): void;
70
+ silly(message: unknown, ...meta: unknown[]): void;
71
+ log(level: LogLevel, message: unknown, ...meta: unknown[]): void;
72
+ settings(options?: LogSettingsOptions): void;
73
+ setLevel(level: LogLevel): void;
74
+ getLevel(): string;
75
+ child(meta?: Record<string, unknown>): ChildLogger;
76
+ close(): void;
77
+ createLogger(options?: LogSettingsOptions): LogXpert;
78
+ }
54
79
  }
55
80
 
56
- declare const log: LogXpert;
57
- export default log;
81
+ declare const log: log.LogXpert;
82
+
83
+ export = log;
package/lib/files.js ADDED
@@ -0,0 +1,102 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const { sanitizeAppName, isPadChar, assertFilenameSafe } = require('./sanitize');
4
+
5
+ let cachedAppName = null;
6
+ function getDefaultAppName() {
7
+ if (cachedAppName) return cachedAppName;
8
+ try {
9
+ const pkgPath = path.resolve(process.cwd(), 'package.json');
10
+ const raw = fs.readFileSync(pkgPath, 'utf8');
11
+ cachedAppName = sanitizeAppName(JSON.parse(raw)?.name) ?? 'application';
12
+ } catch {
13
+ cachedAppName = 'application';
14
+ }
15
+ return cachedAppName;
16
+ }
17
+
18
+ function resolveRunNumber(folder, prefix, opt) {
19
+ let enabled = false;
20
+ let separator = '-';
21
+ let padding = 0;
22
+ let startAt = 1;
23
+ if (opt === true) {
24
+ enabled = true;
25
+ } else if (opt && typeof opt === 'object') {
26
+ enabled = opt.enabled ?? true;
27
+ if (opt.separator !== undefined) {
28
+ if (typeof opt.separator !== 'string' || !opt.separator) throw new Error('files.runNumber.separator must be a non-empty string');
29
+ separator = opt.separator;
30
+ }
31
+ if (opt.padding !== undefined) {
32
+ if (!Number.isInteger(opt.padding) || opt.padding < 0) throw new Error('files.runNumber.padding must be a non-negative integer');
33
+ padding = opt.padding;
34
+ }
35
+ if (opt.startAt !== undefined) {
36
+ if (!Number.isInteger(opt.startAt) || opt.startAt < 0) throw new Error('files.runNumber.startAt must be a non-negative integer');
37
+ startAt = opt.startAt;
38
+ }
39
+ } else if (opt !== undefined && opt !== false) {
40
+ throw new Error('files.runNumber must be a boolean or an object');
41
+ }
42
+ if (!enabled) return null;
43
+ const counterFile = path.join(folder, `.${prefix}.run`);
44
+ let next = startAt;
45
+ try {
46
+ const raw = fs.readFileSync(counterFile, 'utf8').trim();
47
+ const prev = parseInt(raw, 10);
48
+ next = Number.isInteger(prev) ? prev + 1 : startAt;
49
+ } catch {}
50
+ try {
51
+ fs.writeFileSync(counterFile, String(next), 'utf8');
52
+ } catch {}
53
+ return separator + String(next).padStart(padding, '0');
54
+ }
55
+
56
+ function normalizeFilesOptions(files = {}) {
57
+ const rawFolder = files.folder ?? 'logs';
58
+ if (typeof rawFolder !== 'string' || !rawFolder.trim() || rawFolder.includes('\0')) {
59
+ throw new Error('files.folder must be a non-empty string');
60
+ }
61
+ const folder = path.normalize(rawFolder);
62
+ const datePattern = files.datePattern ?? files.dateFormat ?? files.filesName ?? 'YYYY_MM_DD';
63
+ if (typeof datePattern !== 'string' || !datePattern.trim()) {
64
+ throw new Error('files.datePattern must be a non-empty string');
65
+ }
66
+ const explicitPattern = files.filePattern ?? files.pattern ?? files.filename;
67
+ const explicitPrefix = files.prefix ?? files.appName;
68
+ if (explicitPattern !== undefined && explicitPrefix !== undefined) {
69
+ throw new Error('Do not combine "prefix" with "filePattern", pick one: prefix builds "<prefix>-%DATE%.log" for you, filePattern takes full control');
70
+ }
71
+ let filename = explicitPattern ?? `${sanitizeAppName(explicitPrefix) ?? getDefaultAppName()}-%DATE%.log`;
72
+ filename = filename.split('%datePattern%').join('%DATE%');
73
+ assertFilenameSafe(filename);
74
+ if (!filename.includes('%DATE%')) {
75
+ const ext = path.extname(filename) || '.log';
76
+ const base = path.basename(filename, ext);
77
+ filename = `${base}-%DATE%${ext}`;
78
+ }
79
+ assertFilenameSafe(filename);
80
+ if (!fs.existsSync(folder)) fs.mkdirSync(folder, { recursive: true });
81
+ const rawPrefix = path.basename(filename).split('%DATE%')[0];
82
+ let prefixEnd = rawPrefix.length;
83
+ while (prefixEnd > 0 && isPadChar(rawPrefix[prefixEnd - 1])) prefixEnd--;
84
+ const prefix = rawPrefix.slice(0, prefixEnd) || 'application';
85
+ const runSuffix = resolveRunNumber(folder, sanitizeAppName(prefix) ?? 'application', files.runNumber ?? false);
86
+ if (runSuffix) {
87
+ const ext = path.extname(filename) || '.log';
88
+ const base = filename.slice(0, -ext.length);
89
+ filename = `${base}${runSuffix}${ext}`;
90
+ }
91
+ return {
92
+ folder,
93
+ datePattern,
94
+ filename,
95
+ maxFiles: files.maxFile ?? files.maxFiles ?? '14d',
96
+ maxSize: files.maxSize ?? '20m',
97
+ zippedArchive: files.zippedArchive ?? false,
98
+ level: files.level,
99
+ };
100
+ }
101
+
102
+ module.exports = { getDefaultAppName, resolveRunNumber, normalizeFilesOptions };
package/lib/format.js ADDED
@@ -0,0 +1,38 @@
1
+ const util = require('util');
2
+
3
+ function formatExtra(meta) {
4
+ const keys = Object.keys(meta).filter((k) => k !== 'splat' && k !== 'ms');
5
+ if (!keys.length) return '';
6
+ try {
7
+ const picked = {};
8
+ for (const k of keys) picked[k] = meta[k];
9
+ return JSON.stringify(picked);
10
+ } catch {
11
+ return '';
12
+ }
13
+ }
14
+
15
+ function mergeMeta(meta) {
16
+ const out = {};
17
+ for (const m of meta) {
18
+ if (m && typeof m === 'object') Object.assign(out, m);
19
+ }
20
+ return out;
21
+ }
22
+
23
+ function renderBody(message, meta) {
24
+ if (typeof message === 'string' && meta.length && /%[sdifoO%]/.test(message)) {
25
+ return util.format(message, ...meta);
26
+ }
27
+ const msg = typeof message === 'string' ? message : message == null ? '' : JSON.stringify(message);
28
+ const extra = formatExtra(mergeMeta(meta));
29
+ return [msg, extra].filter(Boolean).join(' ');
30
+ }
31
+
32
+ function buildLine(timestamp, level, message, meta, tag) {
33
+ const body = renderBody(message, meta);
34
+ const label = tag ?? `[${level}]`;
35
+ return timestamp ? `${timestamp} ${label}: ${body}` : `${label}: ${body}`;
36
+ }
37
+
38
+ module.exports = { formatExtra, mergeMeta, renderBody, buildLine };
package/lib/mini.js ADDED
@@ -0,0 +1,134 @@
1
+ const LEVELS = {
2
+ error: 0,
3
+ warn: 1,
4
+ info: 2,
5
+ http: 3,
6
+ verbose: 4,
7
+ debug: 5,
8
+ silly: 6,
9
+ };
10
+
11
+ const COLORS = {
12
+ error: 31,
13
+ warn: 33,
14
+ info: 32,
15
+ http: 35,
16
+ verbose: 36,
17
+ debug: 34,
18
+ silly: 90,
19
+ };
20
+
21
+ const NAMED_COLORS = {
22
+ black: 30,
23
+ red: 31,
24
+ green: 32,
25
+ yellow: 33,
26
+ blue: 34,
27
+ magenta: 35,
28
+ cyan: 36,
29
+ white: 37,
30
+ gray: 90,
31
+ grey: 90,
32
+ };
33
+
34
+ function resolveColorCode(value, level) {
35
+ if (value === undefined || value === null || value === false) return null;
36
+ if (typeof value === 'number' && Number.isInteger(value) && value >= 0 && value <= 255) return value;
37
+ if (typeof value === 'string' && NAMED_COLORS[value.toLowerCase()] !== undefined) return NAMED_COLORS[value.toLowerCase()];
38
+ throw new Error(`Unknown color "${value}" for level "${level}". Use one of: ${Object.keys(NAMED_COLORS).join(', ')}, an ANSI code 0-255, or false to disable`);
39
+ }
40
+
41
+ function resolveLevelColors(custom = {}) {
42
+ if (custom === null || typeof custom !== 'object' || Array.isArray(custom)) {
43
+ throw new Error('console.colors must be an object mapping level names to colors');
44
+ }
45
+ const map = {};
46
+ for (const level of Object.keys(COLORS)) {
47
+ if (custom[level] !== undefined) {
48
+ const code = resolveColorCode(custom[level], level);
49
+ if (code !== null) map[level] = code;
50
+ } else {
51
+ map[level] = COLORS[level];
52
+ }
53
+ }
54
+ return map;
55
+ }
56
+
57
+ function colorizeLevel(level, text, colors = COLORS) {
58
+ const code = colors[level] ?? 0;
59
+ if (!code) return text;
60
+ return `\x1b[${code}m${text}\x1b[0m`;
61
+ }
62
+
63
+ class NullTransport {
64
+ constructor() {
65
+ this.level = 'off';
66
+ }
67
+
68
+ write() {}
69
+
70
+ close() {}
71
+ }
72
+
73
+ class ConsoleTransport {
74
+ constructor({ level, render } = {}) {
75
+ this.level = level;
76
+ this.render = render;
77
+ }
78
+
79
+ write(entry) {
80
+ const line = this.render(entry);
81
+ const stream = entry.level === 'error' || entry.level === 'warn' ? process.stderr : process.stdout;
82
+ stream.write(line + '\n');
83
+ }
84
+
85
+ close() {}
86
+ }
87
+
88
+ class MiniLogger {
89
+ constructor({ level = 'debug' } = {}) {
90
+ this.level = level;
91
+ this.levels = LEVELS;
92
+ this.transports = [];
93
+ }
94
+
95
+ add(transport) {
96
+ this.transports.push(transport);
97
+ return this;
98
+ }
99
+
100
+ remove(transport) {
101
+ const i = this.transports.indexOf(transport);
102
+ if (i >= 0) this.transports.splice(i, 1);
103
+ try {
104
+ transport.close?.();
105
+ } catch {}
106
+ return this;
107
+ }
108
+
109
+ enabled(level, transportLevel) {
110
+ const want = LEVELS[level];
111
+ const current = LEVELS[transportLevel ?? this.level];
112
+ return want !== undefined && current !== undefined && want <= current;
113
+ }
114
+
115
+ log(level, message, ...meta) {
116
+ for (const t of [...this.transports]) {
117
+ if (this.enabled(level, t.level)) t.write({ level, message, meta });
118
+ }
119
+ }
120
+
121
+ child(meta = {}) {
122
+ const self = this;
123
+ const make = (level) => (message, ...args) => self.log(level, message, meta, ...args);
124
+ return {
125
+ error: make('error'),
126
+ warn: make('warn'),
127
+ info: make('info'),
128
+ debug: make('debug'),
129
+ log: (level, message, ...args) => self.log(level, message, meta, ...args),
130
+ };
131
+ }
132
+ }
133
+
134
+ module.exports = { LEVELS, ConsoleTransport, NullTransport, MiniLogger, colorizeLevel, resolveLevelColors, NAMED_COLORS };