@vvlad1973/simple-logger 2.1.10 → 2.2.1
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/dist/__test__/simple-logger.test.js +377 -48
- package/dist/__test__/simple-logger.test.js.map +1 -1
- package/dist/classes/simple-logger.d.ts +8 -1
- package/dist/classes/simple-logger.js +47 -13
- package/dist/classes/simple-logger.js.map +1 -1
- package/dist/helpers/helpers.d.ts +6 -0
- package/dist/helpers/helpers.js +20 -7
- package/dist/helpers/helpers.js.map +1 -1
- package/dist/helpers/validators.d.ts +2 -2
- package/dist/helpers/validators.js +13 -4
- package/dist/helpers/validators.js.map +1 -1
- package/dist/types/simple-logger.types.d.ts +1 -2
- package/eslint.config.js +14 -0
- package/package.json +2 -2
- package/src/__test__/simple-logger.test.ts +485 -55
- package/src/classes/simple-logger.ts +67 -23
- package/src/helpers/helpers.ts +21 -3
- package/src/helpers/validators.ts +16 -7
- package/src/types/simple-logger.types.ts +1 -2
- package/tsconfig.json +2 -1
- package/vitest.config.ts +1 -1
|
@@ -13,13 +13,12 @@ import {
|
|
|
13
13
|
prepareLogCall,
|
|
14
14
|
} from '../helpers/helpers.js';
|
|
15
15
|
import { LoggerLevels } from '../constants/constants.js';
|
|
16
|
-
import {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
PreparedLogCall,
|
|
16
|
+
import type {
|
|
17
|
+
ExternalLogger,
|
|
18
|
+
LogFn,
|
|
19
|
+
LoggerFactory,
|
|
20
|
+
LoggerLevel,
|
|
21
|
+
LoggerOptions,
|
|
23
22
|
} from '../types/simple-logger.types.js';
|
|
24
23
|
|
|
25
24
|
export default class SimpleLogger {
|
|
@@ -69,13 +68,13 @@ export default class SimpleLogger {
|
|
|
69
68
|
const levels = Object.values(LoggerLevels);
|
|
70
69
|
if (explicitLevel) return explicitLevel;
|
|
71
70
|
if (
|
|
72
|
-
logger &&
|
|
73
|
-
typeof logger === 'object' &&
|
|
74
71
|
'level' in logger &&
|
|
75
|
-
typeof
|
|
72
|
+
typeof logger.level === 'string'
|
|
76
73
|
) {
|
|
77
|
-
const lvl =
|
|
78
|
-
|
|
74
|
+
const lvl = logger.level.toLowerCase();
|
|
75
|
+
const isValidLevel = (value: string): value is LoggerLevel =>
|
|
76
|
+
(levels as readonly string[]).includes(value);
|
|
77
|
+
if (isValidLevel(lvl)) return lvl;
|
|
79
78
|
}
|
|
80
79
|
return levels[this.currentLevelIndex];
|
|
81
80
|
}
|
|
@@ -108,9 +107,9 @@ export default class SimpleLogger {
|
|
|
108
107
|
} = options;
|
|
109
108
|
|
|
110
109
|
const hasParams =
|
|
111
|
-
level ||
|
|
112
|
-
msgPrefix ||
|
|
113
|
-
transport ||
|
|
110
|
+
level !== undefined ||
|
|
111
|
+
msgPrefix !== undefined ||
|
|
112
|
+
transport !== undefined ||
|
|
114
113
|
Object.keys(bindings).length > 0 ||
|
|
115
114
|
Object.keys(restOptions).length > 0;
|
|
116
115
|
const effectiveBindings = {
|
|
@@ -229,7 +228,31 @@ export default class SimpleLogger {
|
|
|
229
228
|
const prepared = prepareLogCall(args);
|
|
230
229
|
|
|
231
230
|
if (prepared !== null) {
|
|
232
|
-
|
|
231
|
+
const [first, ...rest] = prepared;
|
|
232
|
+
if (typeof first === 'string') {
|
|
233
|
+
// Call with string message signature: (msg: string, ...args: unknown[])
|
|
234
|
+
method.call(this.logger, first, ...rest);
|
|
235
|
+
} else if (typeof first === 'object') {
|
|
236
|
+
// Call with object signature: (obj: object, msg?: string, ...args: unknown[])
|
|
237
|
+
const [second, ...otherRest] = rest;
|
|
238
|
+
if (typeof second === 'string') {
|
|
239
|
+
// Call with both object and message
|
|
240
|
+
(method as (obj: object, msg: string, ...args: unknown[]) => void).call(
|
|
241
|
+
this.logger,
|
|
242
|
+
first,
|
|
243
|
+
second,
|
|
244
|
+
...otherRest
|
|
245
|
+
);
|
|
246
|
+
} else {
|
|
247
|
+
// Call with object only (msg is undefined)
|
|
248
|
+
(method as (obj: object, msg?: string, ...args: unknown[]) => void).call(
|
|
249
|
+
this.logger,
|
|
250
|
+
first,
|
|
251
|
+
undefined,
|
|
252
|
+
...otherRest
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
233
256
|
} else {
|
|
234
257
|
console.warn(`Invalid log arguments for "${level}"`, args);
|
|
235
258
|
}
|
|
@@ -250,7 +273,7 @@ export default class SimpleLogger {
|
|
|
250
273
|
const fullMsg = util.format(msg, ...rest);
|
|
251
274
|
|
|
252
275
|
const ctx = Object.entries({ ...this.bindings, ...context })
|
|
253
|
-
.map(([k, v]) => `${k}=${v}`)
|
|
276
|
+
.map(([k, v]) => `${k}=${String(v)}`)
|
|
254
277
|
.join(' ');
|
|
255
278
|
|
|
256
279
|
const prefix = `[${time}] ${levelStr}`;
|
|
@@ -318,11 +341,7 @@ export default class SimpleLogger {
|
|
|
318
341
|
public child(newBindings: Record<string, unknown>): SimpleLogger {
|
|
319
342
|
const merged = { ...this.bindings, ...newBindings };
|
|
320
343
|
|
|
321
|
-
if (
|
|
322
|
-
this.isExternal &&
|
|
323
|
-
typeof this.logger === 'object' &&
|
|
324
|
-
this.logger !== null
|
|
325
|
-
) {
|
|
344
|
+
if (this.isExternal) {
|
|
326
345
|
const logger = this.logger as ExternalLogger;
|
|
327
346
|
const childFn = logger.child;
|
|
328
347
|
|
|
@@ -359,7 +378,32 @@ export default class SimpleLogger {
|
|
|
359
378
|
* @return {void}
|
|
360
379
|
*/
|
|
361
380
|
public logFunctionEnd(name?: string): void {
|
|
362
|
-
const caller = name
|
|
381
|
+
const caller = name ?? getCallerName();
|
|
363
382
|
this.trace(`Function end: ${caller}`);
|
|
364
383
|
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Flushes the logger buffer if the external logger supports it.
|
|
387
|
+
* This is useful for ensuring all buffered log entries are written before the application exits.
|
|
388
|
+
*
|
|
389
|
+
* @return {Promise<void>} A promise that resolves when the flush is complete.
|
|
390
|
+
*/
|
|
391
|
+
public async flush(): Promise<void> {
|
|
392
|
+
if (!this.isExternal) {
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
const logger = this.logger as ExternalLogger & {
|
|
397
|
+
flush?: (callback: (err?: Error) => void) => void;
|
|
398
|
+
};
|
|
399
|
+
|
|
400
|
+
if (typeof logger.flush === 'function') {
|
|
401
|
+
try {
|
|
402
|
+
const promisifiedFlush = util.promisify(logger.flush.bind(logger));
|
|
403
|
+
return await promisifiedFlush();
|
|
404
|
+
} catch {
|
|
405
|
+
// Ignore flush errors - they're not critical
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
365
409
|
}
|
package/src/helpers/helpers.ts
CHANGED
|
@@ -36,6 +36,22 @@ export function extractMessage(args: unknown[]): {
|
|
|
36
36
|
return { msg: '', rest: [] };
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Type guard to check if value is a plain object record.
|
|
41
|
+
*
|
|
42
|
+
* @param {unknown} value - The value to check.
|
|
43
|
+
* @return {value is Record<string, unknown>} True if the value is a plain object.
|
|
44
|
+
*/
|
|
45
|
+
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
46
|
+
return (
|
|
47
|
+
typeof value === 'object' &&
|
|
48
|
+
value !== null &&
|
|
49
|
+
!Array.isArray(value) &&
|
|
50
|
+
(Object.getPrototypeOf(value) === Object.prototype ||
|
|
51
|
+
Object.getPrototypeOf(value) === null)
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
39
55
|
/**
|
|
40
56
|
* Extracts the context object from the provided array of arguments.
|
|
41
57
|
*
|
|
@@ -44,8 +60,8 @@ export function extractMessage(args: unknown[]): {
|
|
|
44
60
|
*/
|
|
45
61
|
export function extractContext(args: unknown[]): Record<string, unknown> {
|
|
46
62
|
const [first] = args;
|
|
47
|
-
if (
|
|
48
|
-
return first
|
|
63
|
+
if (isPlainObject(first)) {
|
|
64
|
+
return first;
|
|
49
65
|
}
|
|
50
66
|
return {};
|
|
51
67
|
}
|
|
@@ -72,13 +88,15 @@ export function colorizeLevel(level: LoggerLevel, label: string): string {
|
|
|
72
88
|
default:
|
|
73
89
|
return label;
|
|
74
90
|
}
|
|
91
|
+
}
|
|
92
|
+
|
|
75
93
|
/**
|
|
76
94
|
* Prepares the log call by rearranging the provided arguments into a standardized format.
|
|
77
95
|
*
|
|
78
96
|
* @param {unknown[]} args - The array of arguments to prepare for the log call.
|
|
79
97
|
* @return {PreparedLogCall} The prepared log call arguments, or null if the input is invalid.
|
|
80
98
|
*/
|
|
81
|
-
|
|
99
|
+
export function prepareLogCall(args: unknown[]): PreparedLogCall {
|
|
82
100
|
if (typeof args[0] === 'string') {
|
|
83
101
|
return [args[0], ...args.slice(1)];
|
|
84
102
|
}
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import { LoggerLevels } from '../constants/constants.js';
|
|
2
2
|
import type { ExternalLogger } from '../types/simple-logger.types.js';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Type guard to check if value is an object with properties.
|
|
6
|
+
*
|
|
7
|
+
* @param {unknown} value - The value to check.
|
|
8
|
+
* @return {value is Record<string, unknown>} True if the value is an object.
|
|
9
|
+
*/
|
|
10
|
+
function isObjectWithProperties(value: unknown): value is Record<string, unknown> {
|
|
11
|
+
return typeof value === 'object' && value !== null;
|
|
12
|
+
}
|
|
13
|
+
|
|
4
14
|
/**
|
|
5
15
|
* Checks if the provided logger is a valid ExternalLogger instance.
|
|
6
16
|
*
|
|
@@ -10,27 +20,26 @@ import type { ExternalLogger } from '../types/simple-logger.types.js';
|
|
|
10
20
|
export function isValidLogger(logger: unknown): logger is ExternalLogger {
|
|
11
21
|
const levels = Object.values(LoggerLevels);
|
|
12
22
|
|
|
13
|
-
if (
|
|
23
|
+
if (!isObjectWithProperties(logger)) {
|
|
14
24
|
return false;
|
|
15
25
|
}
|
|
16
26
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
return levels.some((level) => typeof candidate[level] === 'function');
|
|
27
|
+
return levels.some((level) => typeof logger[level] === 'function');
|
|
20
28
|
}
|
|
21
29
|
|
|
22
30
|
/**
|
|
23
31
|
* Checks if the provided logger is an ExternalLogger instance with a child method.
|
|
24
32
|
*
|
|
25
33
|
* @param {unknown} logger - The logger to check.
|
|
26
|
-
* @return {logger is ExternalLogger & { child:
|
|
34
|
+
* @return {logger is ExternalLogger & { child: (bindings: Record<string, unknown>, options?: Record<string, unknown>) => ExternalLogger }} True if the logger is an ExternalLogger with a child method, false otherwise.
|
|
27
35
|
*/
|
|
28
36
|
export function hasChild(
|
|
29
37
|
logger: unknown
|
|
30
|
-
): logger is ExternalLogger & { child:
|
|
38
|
+
): logger is ExternalLogger & { child: (bindings: Record<string, unknown>, options?: Record<string, unknown>) => ExternalLogger } {
|
|
31
39
|
return (
|
|
32
40
|
typeof logger === 'object' &&
|
|
33
41
|
logger !== null &&
|
|
34
|
-
|
|
42
|
+
'child' in logger &&
|
|
43
|
+
typeof logger.child === 'function'
|
|
35
44
|
);
|
|
36
45
|
}
|
|
@@ -3,8 +3,7 @@ import type { LoggerLevels } from '../constants/constants';
|
|
|
3
3
|
export type LoggerLevel = (typeof LoggerLevels)[keyof typeof LoggerLevels];
|
|
4
4
|
|
|
5
5
|
export interface LogFn {
|
|
6
|
-
|
|
7
|
-
(obj: unknown, msg?: string, ...args: unknown[]): void;
|
|
6
|
+
(obj: object, msg?: string, ...args: unknown[]): void;
|
|
8
7
|
(msg: string, ...args: unknown[]): void;
|
|
9
8
|
}
|
|
10
9
|
|
package/tsconfig.json
CHANGED
package/vitest.config.ts
CHANGED
|
@@ -12,6 +12,7 @@ export default defineConfig({
|
|
|
12
12
|
include: ['src/**/*.test.ts'],
|
|
13
13
|
exclude: ['node_modules/**', 'dist/**', 'docs/**'],
|
|
14
14
|
coverage: {
|
|
15
|
+
enabled: true,
|
|
15
16
|
provider: 'v8',
|
|
16
17
|
reporter: ['text', 'json', 'html', 'lcov'],
|
|
17
18
|
include: ['src/**/*.ts'],
|
|
@@ -22,7 +23,6 @@ export default defineConfig({
|
|
|
22
23
|
'**/*.test.ts',
|
|
23
24
|
'**/*.config.ts',
|
|
24
25
|
'**/*.config.js',
|
|
25
|
-
'src/__test__/**'
|
|
26
26
|
],
|
|
27
27
|
thresholds: {
|
|
28
28
|
lines: 80,
|