@geekmidas/logger 0.3.0 → 1.0.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.
Files changed (41) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/console.cjs.map +1 -1
  3. package/dist/console.d.cts +2 -1
  4. package/dist/console.d.cts.map +1 -0
  5. package/dist/console.d.mts +2 -1
  6. package/dist/console.d.mts.map +1 -0
  7. package/dist/console.mjs.map +1 -1
  8. package/dist/index.d.cts +1 -1
  9. package/dist/index.d.mts +1 -1
  10. package/dist/pino.cjs.map +1 -1
  11. package/dist/pino.d.cts +3 -2
  12. package/dist/pino.d.cts.map +1 -0
  13. package/dist/pino.d.mts +3 -2
  14. package/dist/pino.d.mts.map +1 -0
  15. package/dist/pino.mjs.map +1 -1
  16. package/dist/{redact-paths-Br-tI2GZ.d.cts → redact-paths-CsK0_uz-.d.cts} +2 -1
  17. package/dist/redact-paths-CsK0_uz-.d.cts.map +1 -0
  18. package/dist/{redact-paths-CIsuxHH7.d.mts → redact-paths-D07eTMlH.d.mts} +2 -1
  19. package/dist/redact-paths-D07eTMlH.d.mts.map +1 -0
  20. package/dist/redact-paths-D0m0DIuQ.cjs.map +1 -1
  21. package/dist/redact-paths-DQoIXhkS.mjs.map +1 -1
  22. package/dist/redact-paths.d.cts +1 -1
  23. package/dist/redact-paths.d.mts +1 -1
  24. package/dist/{types-Bga8WDuP.d.mts → types-BDdpcrpy.d.mts} +2 -1
  25. package/dist/types-BDdpcrpy.d.mts.map +1 -0
  26. package/dist/{types-JxCFymH0.d.cts → types-Dk_k2-f_.d.cts} +2 -1
  27. package/dist/types-Dk_k2-f_.d.cts.map +1 -0
  28. package/dist/types-ag_0Cvbg.cjs.map +1 -1
  29. package/dist/types-yQ6XOihF.mjs.map +1 -1
  30. package/dist/types.d.cts +1 -1
  31. package/dist/types.d.mts +1 -1
  32. package/package.json +1 -1
  33. package/src/__tests__/console.spec.ts +648 -648
  34. package/src/__tests__/pino-redaction.integration.spec.ts +270 -270
  35. package/src/__tests__/pino.spec.ts +305 -305
  36. package/src/console.ts +100 -100
  37. package/src/index.ts +5 -5
  38. package/src/pino.ts +50 -50
  39. package/src/redact-paths.ts +52 -52
  40. package/src/types.ts +87 -87
  41. package/tsconfig.json +9 -0
@@ -3,661 +3,661 @@ import { ConsoleLogger, createLogger } from '../console';
3
3
  import { LogLevel } from '../types';
4
4
 
5
5
  describe('ConsoleLogger', () => {
6
- // Mock console methods
7
- const originalConsole = {
8
- debug: console.debug,
9
- info: console.info,
10
- warn: console.warn,
11
- error: console.error,
12
- trace: console.trace,
13
- };
14
-
15
- beforeEach(() => {
16
- // Mock all console methods
17
- console.debug = vi.fn();
18
- console.info = vi.fn();
19
- console.warn = vi.fn();
20
- console.error = vi.fn();
21
- console.trace = vi.fn();
22
-
23
- // Mock Date.now for predictable timestamps
24
- vi.spyOn(Date, 'now').mockReturnValue(1234567890);
25
- });
26
-
27
- afterEach(() => {
28
- // Restore console methods
29
- console.debug = originalConsole.debug;
30
- console.info = originalConsole.info;
31
- console.warn = originalConsole.warn;
32
- console.error = originalConsole.error;
33
- console.trace = originalConsole.trace;
34
-
35
- vi.restoreAllMocks();
36
- });
37
-
38
- describe('Constructor', () => {
39
- it('should create logger with no initial context', () => {
40
- const logger = new ConsoleLogger();
41
-
42
- expect(logger.data).toEqual({});
43
- });
44
-
45
- it('should create logger with initial context', () => {
46
- const logger = new ConsoleLogger({ app: 'myApp', version: '1.0.0' });
47
-
48
- expect(logger.data).toEqual({ app: 'myApp', version: '1.0.0' });
49
- });
50
- });
51
-
52
- describe('Log levels', () => {
53
- describe('debug', () => {
54
- it('should log debug message with context when level is Debug', () => {
55
- const logger = new ConsoleLogger({ app: 'test' }, LogLevel.Debug);
56
-
57
- logger.debug({ userId: 123 }, 'Debug message');
58
-
59
- expect(console.debug).toHaveBeenCalledWith({
60
- app: 'test',
61
- userId: 123,
62
- msg: 'Debug message',
63
- ts: 1234567890,
64
- });
65
- });
66
-
67
- it('should log debug with only context object when level is Debug', () => {
68
- const logger = new ConsoleLogger({}, LogLevel.Debug);
69
-
70
- logger.debug({ action: 'test' });
71
-
72
- expect(console.debug).toHaveBeenCalledWith({
73
- action: 'test',
74
- ts: 1234567890,
75
- });
76
- });
77
- });
78
-
79
- describe('info', () => {
80
- it('should log info message with context', () => {
81
- const logger = new ConsoleLogger({ app: 'test' });
82
-
83
- logger.info({ userId: 123 }, 'Info message');
84
-
85
- expect(console.info).toHaveBeenCalledWith({
86
- app: 'test',
87
- userId: 123,
88
- msg: 'Info message',
89
- ts: 1234567890,
90
- });
91
- });
92
-
93
- it('should log info with only context object', () => {
94
- const logger = new ConsoleLogger();
95
-
96
- logger.info({ status: 'success' });
97
-
98
- expect(console.info).toHaveBeenCalledWith({
99
- status: 'success',
100
- ts: 1234567890,
101
- });
102
- });
103
- });
104
-
105
- describe('warn', () => {
106
- it('should log warning message with context', () => {
107
- const logger = new ConsoleLogger({ app: 'test' });
108
-
109
- logger.warn({ code: 'DEPRECATED' }, 'Warning message');
110
-
111
- expect(console.warn).toHaveBeenCalledWith({
112
- app: 'test',
113
- code: 'DEPRECATED',
114
- msg: 'Warning message',
115
- ts: 1234567890,
116
- });
117
- });
118
-
119
- it('should log warning with only context object', () => {
120
- const logger = new ConsoleLogger();
121
-
122
- logger.warn({ issue: 'memory' });
123
-
124
- expect(console.warn).toHaveBeenCalledWith({
125
- issue: 'memory',
126
- ts: 1234567890,
127
- });
128
- });
129
- });
130
-
131
- describe('error', () => {
132
- it('should log error message with context', () => {
133
- const logger = new ConsoleLogger({ app: 'test' });
134
- const error = new Error('Test error');
135
-
136
- logger.error({ error }, 'Error occurred');
6
+ // Mock console methods
7
+ const originalConsole = {
8
+ debug: console.debug,
9
+ info: console.info,
10
+ warn: console.warn,
11
+ error: console.error,
12
+ trace: console.trace,
13
+ };
14
+
15
+ beforeEach(() => {
16
+ // Mock all console methods
17
+ console.debug = vi.fn();
18
+ console.info = vi.fn();
19
+ console.warn = vi.fn();
20
+ console.error = vi.fn();
21
+ console.trace = vi.fn();
22
+
23
+ // Mock Date.now for predictable timestamps
24
+ vi.spyOn(Date, 'now').mockReturnValue(1234567890);
25
+ });
26
+
27
+ afterEach(() => {
28
+ // Restore console methods
29
+ console.debug = originalConsole.debug;
30
+ console.info = originalConsole.info;
31
+ console.warn = originalConsole.warn;
32
+ console.error = originalConsole.error;
33
+ console.trace = originalConsole.trace;
34
+
35
+ vi.restoreAllMocks();
36
+ });
37
+
38
+ describe('Constructor', () => {
39
+ it('should create logger with no initial context', () => {
40
+ const logger = new ConsoleLogger();
41
+
42
+ expect(logger.data).toEqual({});
43
+ });
44
+
45
+ it('should create logger with initial context', () => {
46
+ const logger = new ConsoleLogger({ app: 'myApp', version: '1.0.0' });
47
+
48
+ expect(logger.data).toEqual({ app: 'myApp', version: '1.0.0' });
49
+ });
50
+ });
51
+
52
+ describe('Log levels', () => {
53
+ describe('debug', () => {
54
+ it('should log debug message with context when level is Debug', () => {
55
+ const logger = new ConsoleLogger({ app: 'test' }, LogLevel.Debug);
56
+
57
+ logger.debug({ userId: 123 }, 'Debug message');
58
+
59
+ expect(console.debug).toHaveBeenCalledWith({
60
+ app: 'test',
61
+ userId: 123,
62
+ msg: 'Debug message',
63
+ ts: 1234567890,
64
+ });
65
+ });
66
+
67
+ it('should log debug with only context object when level is Debug', () => {
68
+ const logger = new ConsoleLogger({}, LogLevel.Debug);
69
+
70
+ logger.debug({ action: 'test' });
71
+
72
+ expect(console.debug).toHaveBeenCalledWith({
73
+ action: 'test',
74
+ ts: 1234567890,
75
+ });
76
+ });
77
+ });
78
+
79
+ describe('info', () => {
80
+ it('should log info message with context', () => {
81
+ const logger = new ConsoleLogger({ app: 'test' });
82
+
83
+ logger.info({ userId: 123 }, 'Info message');
84
+
85
+ expect(console.info).toHaveBeenCalledWith({
86
+ app: 'test',
87
+ userId: 123,
88
+ msg: 'Info message',
89
+ ts: 1234567890,
90
+ });
91
+ });
92
+
93
+ it('should log info with only context object', () => {
94
+ const logger = new ConsoleLogger();
95
+
96
+ logger.info({ status: 'success' });
97
+
98
+ expect(console.info).toHaveBeenCalledWith({
99
+ status: 'success',
100
+ ts: 1234567890,
101
+ });
102
+ });
103
+ });
104
+
105
+ describe('warn', () => {
106
+ it('should log warning message with context', () => {
107
+ const logger = new ConsoleLogger({ app: 'test' });
108
+
109
+ logger.warn({ code: 'DEPRECATED' }, 'Warning message');
110
+
111
+ expect(console.warn).toHaveBeenCalledWith({
112
+ app: 'test',
113
+ code: 'DEPRECATED',
114
+ msg: 'Warning message',
115
+ ts: 1234567890,
116
+ });
117
+ });
118
+
119
+ it('should log warning with only context object', () => {
120
+ const logger = new ConsoleLogger();
121
+
122
+ logger.warn({ issue: 'memory' });
123
+
124
+ expect(console.warn).toHaveBeenCalledWith({
125
+ issue: 'memory',
126
+ ts: 1234567890,
127
+ });
128
+ });
129
+ });
130
+
131
+ describe('error', () => {
132
+ it('should log error message with context', () => {
133
+ const logger = new ConsoleLogger({ app: 'test' });
134
+ const error = new Error('Test error');
135
+
136
+ logger.error({ error }, 'Error occurred');
137
137
 
138
- expect(console.error).toHaveBeenCalledWith({
139
- app: 'test',
140
- error,
141
- msg: 'Error occurred',
142
- ts: 1234567890,
143
- });
144
- });
138
+ expect(console.error).toHaveBeenCalledWith({
139
+ app: 'test',
140
+ error,
141
+ msg: 'Error occurred',
142
+ ts: 1234567890,
143
+ });
144
+ });
145
145
 
146
- it('should log error with only context object', () => {
147
- const logger = new ConsoleLogger();
148
- const error = new Error('Test error');
146
+ it('should log error with only context object', () => {
147
+ const logger = new ConsoleLogger();
148
+ const error = new Error('Test error');
149
149
 
150
- logger.error({ error });
150
+ logger.error({ error });
151
151
 
152
- expect(console.error).toHaveBeenCalledWith({
153
- error,
154
- ts: 1234567890,
155
- });
156
- });
157
- });
158
-
159
- describe('fatal', () => {
160
- it('should log fatal message with context', () => {
161
- const logger = new ConsoleLogger({ app: 'test' });
162
-
163
- logger.fatal({ exitCode: 1 }, 'Fatal error');
152
+ expect(console.error).toHaveBeenCalledWith({
153
+ error,
154
+ ts: 1234567890,
155
+ });
156
+ });
157
+ });
158
+
159
+ describe('fatal', () => {
160
+ it('should log fatal message with context', () => {
161
+ const logger = new ConsoleLogger({ app: 'test' });
162
+
163
+ logger.fatal({ exitCode: 1 }, 'Fatal error');
164
164
 
165
- expect(console.error).toHaveBeenCalledWith({
166
- app: 'test',
167
- exitCode: 1,
168
- msg: 'Fatal error',
169
- ts: 1234567890,
170
- });
171
- });
172
-
173
- it('should log fatal with only context object', () => {
174
- const logger = new ConsoleLogger();
175
-
176
- logger.fatal({ critical: true });
165
+ expect(console.error).toHaveBeenCalledWith({
166
+ app: 'test',
167
+ exitCode: 1,
168
+ msg: 'Fatal error',
169
+ ts: 1234567890,
170
+ });
171
+ });
172
+
173
+ it('should log fatal with only context object', () => {
174
+ const logger = new ConsoleLogger();
175
+
176
+ logger.fatal({ critical: true });
177
177
 
178
- expect(console.error).toHaveBeenCalledWith({
179
- critical: true,
180
- ts: 1234567890,
181
- });
182
- });
183
- });
184
-
185
- describe('trace', () => {
186
- it('should log trace message with context when level is Trace', () => {
187
- const logger = new ConsoleLogger({ app: 'test' }, LogLevel.Trace);
188
-
189
- logger.trace({ stack: 'trace' }, 'Trace message');
178
+ expect(console.error).toHaveBeenCalledWith({
179
+ critical: true,
180
+ ts: 1234567890,
181
+ });
182
+ });
183
+ });
184
+
185
+ describe('trace', () => {
186
+ it('should log trace message with context when level is Trace', () => {
187
+ const logger = new ConsoleLogger({ app: 'test' }, LogLevel.Trace);
188
+
189
+ logger.trace({ stack: 'trace' }, 'Trace message');
190
190
 
191
- expect(console.trace).toHaveBeenCalledWith({
192
- app: 'test',
193
- stack: 'trace',
194
- msg: 'Trace message',
195
- ts: 1234567890,
196
- });
197
- });
198
-
199
- it('should log trace with only context object when level is Trace', () => {
200
- const logger = new ConsoleLogger({}, LogLevel.Trace);
201
-
202
- logger.trace({ depth: 5 });
203
-
204
- expect(console.trace).toHaveBeenCalledWith({
205
- depth: 5,
206
- ts: 1234567890,
207
- });
208
- });
209
- });
210
- });
211
-
212
- describe('Log level filtering', () => {
213
- it('should not log debug when level is Info', () => {
214
- const logger = new ConsoleLogger({}, LogLevel.Info);
215
-
216
- logger.debug('This should not appear');
217
-
218
- expect(console.debug).not.toHaveBeenCalled();
219
- });
191
+ expect(console.trace).toHaveBeenCalledWith({
192
+ app: 'test',
193
+ stack: 'trace',
194
+ msg: 'Trace message',
195
+ ts: 1234567890,
196
+ });
197
+ });
198
+
199
+ it('should log trace with only context object when level is Trace', () => {
200
+ const logger = new ConsoleLogger({}, LogLevel.Trace);
201
+
202
+ logger.trace({ depth: 5 });
203
+
204
+ expect(console.trace).toHaveBeenCalledWith({
205
+ depth: 5,
206
+ ts: 1234567890,
207
+ });
208
+ });
209
+ });
210
+ });
211
+
212
+ describe('Log level filtering', () => {
213
+ it('should not log debug when level is Info', () => {
214
+ const logger = new ConsoleLogger({}, LogLevel.Info);
215
+
216
+ logger.debug('This should not appear');
217
+
218
+ expect(console.debug).not.toHaveBeenCalled();
219
+ });
220
220
 
221
- it('should not log trace when level is Debug', () => {
222
- const logger = new ConsoleLogger({}, LogLevel.Debug);
223
-
224
- logger.trace('This should not appear');
225
-
226
- expect(console.trace).not.toHaveBeenCalled();
227
- });
228
-
229
- it('should log debug when level is Debug', () => {
230
- const logger = new ConsoleLogger({}, LogLevel.Debug);
231
-
232
- logger.debug('Debug message');
233
-
234
- expect(console.debug).toHaveBeenCalled();
235
- });
236
-
237
- it('should log info when level is Debug', () => {
238
- const logger = new ConsoleLogger({}, LogLevel.Debug);
239
-
240
- logger.info('Info message');
241
-
242
- expect(console.info).toHaveBeenCalled();
243
- });
244
-
245
- it('should not log anything when level is Silent', () => {
246
- const logger = new ConsoleLogger({}, LogLevel.Silent);
221
+ it('should not log trace when level is Debug', () => {
222
+ const logger = new ConsoleLogger({}, LogLevel.Debug);
223
+
224
+ logger.trace('This should not appear');
225
+
226
+ expect(console.trace).not.toHaveBeenCalled();
227
+ });
228
+
229
+ it('should log debug when level is Debug', () => {
230
+ const logger = new ConsoleLogger({}, LogLevel.Debug);
231
+
232
+ logger.debug('Debug message');
233
+
234
+ expect(console.debug).toHaveBeenCalled();
235
+ });
236
+
237
+ it('should log info when level is Debug', () => {
238
+ const logger = new ConsoleLogger({}, LogLevel.Debug);
239
+
240
+ logger.info('Info message');
241
+
242
+ expect(console.info).toHaveBeenCalled();
243
+ });
244
+
245
+ it('should not log anything when level is Silent', () => {
246
+ const logger = new ConsoleLogger({}, LogLevel.Silent);
247
247
 
248
- logger.trace('trace');
249
- logger.debug('debug');
250
- logger.info('info');
251
- logger.warn('warn');
252
- logger.error('error');
253
- logger.fatal('fatal');
254
-
255
- expect(console.trace).not.toHaveBeenCalled();
256
- expect(console.debug).not.toHaveBeenCalled();
257
- expect(console.info).not.toHaveBeenCalled();
258
- expect(console.warn).not.toHaveBeenCalled();
259
- expect(console.error).not.toHaveBeenCalled();
260
- });
261
-
262
- it('should log error when level is Error', () => {
263
- const logger = new ConsoleLogger({}, LogLevel.Error);
264
-
265
- logger.info('This should not appear');
266
- logger.warn('This should not appear');
267
- logger.error('Error message');
268
-
269
- expect(console.info).not.toHaveBeenCalled();
270
- expect(console.warn).not.toHaveBeenCalled();
271
- expect(console.error).toHaveBeenCalled();
272
- });
273
-
274
- it('should inherit log level in child logger', () => {
275
- const parent = new ConsoleLogger({}, LogLevel.Warn);
276
- const child = parent.child({ module: 'test' });
277
-
278
- child.info('This should not appear');
279
- child.warn('Warning message');
280
-
281
- expect(console.info).not.toHaveBeenCalled();
282
- expect(console.warn).toHaveBeenCalled();
283
- });
284
- });
285
-
286
- describe('Context merging', () => {
287
- it('should merge logger context with log context', () => {
288
- const logger = new ConsoleLogger({ app: 'myApp', env: 'production' });
289
-
290
- logger.info({ userId: 123, action: 'login' }, 'User logged in');
291
-
292
- expect(console.info).toHaveBeenCalledWith({
293
- app: 'myApp',
294
- env: 'production',
295
- userId: 123,
296
- action: 'login',
297
- msg: 'User logged in',
298
- ts: 1234567890,
299
- });
300
- });
301
-
302
- it('should override logger context with log context', () => {
303
- const logger = new ConsoleLogger({ env: 'production', status: 'old' });
304
-
305
- logger.info({ status: 'new', userId: 456 }, 'Status updated');
306
-
307
- expect(console.info).toHaveBeenCalledWith({
308
- env: 'production',
309
- status: 'new', // Overridden
310
- userId: 456,
311
- msg: 'Status updated',
312
- ts: 1234567890,
313
- });
314
- });
315
-
316
- it('should always add timestamp', () => {
317
- const logger = new ConsoleLogger();
318
-
319
- logger.info({ action: 'test' }, 'Test message');
320
-
321
- expect(console.info).toHaveBeenCalledWith(
322
- expect.objectContaining({ ts: 1234567890 }),
323
- );
324
- });
325
- });
326
-
327
- describe('Additional arguments', () => {
328
- it('should pass additional arguments to console method', () => {
329
- const logger = new ConsoleLogger();
330
- const obj1 = { key: 'value' };
331
- const obj2 = { another: 'object' };
332
-
333
- logger.info({ action: 'test' }, 'Message', obj1, obj2);
334
-
335
- expect(console.info).toHaveBeenCalledWith(
336
- { action: 'test', msg: 'Message', ts: 1234567890 },
337
- obj1,
338
- obj2,
339
- );
340
- });
341
-
342
- it('should pass additional arguments without message', () => {
343
- const logger = new ConsoleLogger({}, LogLevel.Debug);
344
- const extra = 'extra data';
345
-
346
- logger.debug({ action: 'test' }, undefined as any, extra);
347
-
348
- expect(console.debug).toHaveBeenCalledWith(
349
- { action: 'test', ts: 1234567890 },
350
- extra,
351
- );
352
- });
353
- });
354
-
355
- describe('Child logger', () => {
356
- it('should create child logger with merged context', () => {
357
- const parentLogger = new ConsoleLogger({
358
- app: 'myApp',
359
- version: '1.0.0',
360
- });
361
- const childLogger = parentLogger.child({
362
- module: 'auth',
363
- }) as ConsoleLogger;
364
-
365
- expect(childLogger.data).toEqual({
366
- app: 'myApp',
367
- version: '1.0.0',
368
- module: 'auth',
369
- });
370
- });
371
-
372
- it('should inherit parent context in child logs', () => {
373
- const parentLogger = new ConsoleLogger({ app: 'myApp' });
374
- const childLogger = parentLogger.child({ module: 'database' });
375
-
376
- childLogger.info({ query: 'SELECT *' }, 'Query executed');
377
-
378
- expect(console.info).toHaveBeenCalledWith({
379
- app: 'myApp',
380
- module: 'database',
381
- query: 'SELECT *',
382
- msg: 'Query executed',
383
- ts: 1234567890,
384
- });
385
- });
386
-
387
- it('should override parent context in child logger', () => {
388
- const parentLogger = new ConsoleLogger({ env: 'dev', status: 'parent' });
389
- const childLogger = parentLogger.child({
390
- status: 'child',
391
- module: 'api',
392
- }) as ConsoleLogger;
393
-
394
- expect(childLogger.data).toEqual({
395
- env: 'dev',
396
- status: 'child', // Overridden
397
- module: 'api',
398
- });
399
- });
400
-
401
- it('should create nested child loggers', () => {
402
- const parentLogger = new ConsoleLogger({ app: 'myApp' });
403
- const childLogger = parentLogger.child({ module: 'database' });
404
- const grandchildLogger = childLogger.child({ operation: 'query' });
405
-
406
- grandchildLogger.info({ table: 'users' }, 'Query executed');
407
-
408
- expect(console.info).toHaveBeenCalledWith({
409
- app: 'myApp',
410
- module: 'database',
411
- operation: 'query',
412
- table: 'users',
413
- msg: 'Query executed',
414
- ts: 1234567890,
415
- });
416
- });
417
-
418
- it('should not affect parent logger', () => {
419
- const parentLogger = new ConsoleLogger({ app: 'myApp' });
420
- const childLogger = parentLogger.child({
421
- module: 'auth',
422
- }) as ConsoleLogger;
423
-
424
- // Child logger has additional context
425
- expect(childLogger.data).toEqual({ app: 'myApp', module: 'auth' });
426
-
427
- // Parent logger is unchanged
428
- expect(parentLogger.data).toEqual({ app: 'myApp' });
429
- });
430
- });
431
-
432
- describe('Edge cases', () => {
433
- it('should handle string-only logging without context object', () => {
434
- const logger = new ConsoleLogger({ app: 'test' });
435
-
436
- logger.info('Simple message without context object');
437
-
438
- expect(console.info).toHaveBeenCalledWith({
439
- app: 'test',
440
- msg: 'Simple message without context object',
441
- ts: 1234567890,
442
- });
443
- });
444
-
445
- it('should handle string-only logging with child logger', () => {
446
- const logger = new ConsoleLogger({ app: 'test' });
447
- const child = logger.child({ module: 'auth' });
448
-
449
- child.warn('Warning message');
450
-
451
- expect(console.warn).toHaveBeenCalledWith({
452
- app: 'test',
453
- module: 'auth',
454
- msg: 'Warning message',
455
- ts: 1234567890,
456
- });
457
- });
458
-
459
- it('should handle empty context object', () => {
460
- const logger = new ConsoleLogger();
461
-
462
- logger.info({}, 'Empty context');
463
-
464
- expect(console.info).toHaveBeenCalledWith({
465
- msg: 'Empty context',
466
- ts: 1234567890,
467
- });
468
- });
469
-
470
- it('should handle complex nested objects', () => {
471
- const logger = new ConsoleLogger();
472
- const complexObj = {
473
- user: {
474
- id: 123,
475
- profile: {
476
- name: 'John',
477
- tags: ['admin', 'user'],
478
- },
479
- },
480
- };
481
-
482
- logger.info(complexObj, 'Complex object');
483
-
484
- expect(console.info).toHaveBeenCalledWith({
485
- ...complexObj,
486
- msg: 'Complex object',
487
- ts: 1234567890,
488
- });
489
- });
490
-
491
- it('should handle null and undefined values', () => {
492
- const logger = new ConsoleLogger();
493
-
494
- logger.info({ value: null, missing: undefined }, 'Null values');
495
-
496
- expect(console.info).toHaveBeenCalledWith({
497
- value: null,
498
- missing: undefined,
499
- msg: 'Null values',
500
- ts: 1234567890,
501
- });
502
- });
503
-
504
- it('should handle special characters in strings', () => {
505
- const logger = new ConsoleLogger();
506
-
507
- logger.info({ message: 'Test\n\t"quotes"' }, 'Special chars');
508
-
509
- expect(console.info).toHaveBeenCalledWith({
510
- message: 'Test\n\t"quotes"',
511
- msg: 'Special chars',
512
- ts: 1234567890,
513
- });
514
- });
515
- });
516
-
517
- describe('Real-world scenarios', () => {
518
- it('should log HTTP request', () => {
519
- const logger = new ConsoleLogger({ service: 'api' });
520
-
521
- logger.info(
522
- {
523
- method: 'POST',
524
- path: '/users',
525
- statusCode: 201,
526
- duration: 45,
527
- },
528
- 'HTTP request completed',
529
- );
530
-
531
- expect(console.info).toHaveBeenCalledWith({
532
- service: 'api',
533
- method: 'POST',
534
- path: '/users',
535
- statusCode: 201,
536
- duration: 45,
537
- msg: 'HTTP request completed',
538
- ts: 1234567890,
539
- });
540
- });
541
-
542
- it('should log error with stack trace', () => {
543
- const logger = new ConsoleLogger({ service: 'worker' });
544
- const error = new Error('Database connection failed');
545
-
546
- logger.error(
547
- {
548
- error: error.message,
549
- stack: error.stack,
550
- operation: 'connect',
551
- },
552
- 'Database error',
553
- );
554
-
555
- expect(console.error).toHaveBeenCalledWith(
556
- expect.objectContaining({
557
- service: 'worker',
558
- error: 'Database connection failed',
559
- operation: 'connect',
560
- msg: 'Database error',
561
- ts: 1234567890,
562
- }),
563
- );
564
- });
565
-
566
- it('should log business event', () => {
567
- const logger = new ConsoleLogger({ app: 'ecommerce' });
568
-
569
- logger.info(
570
- {
571
- eventType: 'order.created',
572
- orderId: 'ORD-123',
573
- userId: 456,
574
- amount: 99.99,
575
- currency: 'USD',
576
- },
577
- 'Order created successfully',
578
- );
579
-
580
- expect(console.info).toHaveBeenCalledWith({
581
- app: 'ecommerce',
582
- eventType: 'order.created',
583
- orderId: 'ORD-123',
584
- userId: 456,
585
- amount: 99.99,
586
- currency: 'USD',
587
- msg: 'Order created successfully',
588
- ts: 1234567890,
589
- });
590
- });
591
-
592
- it('should use child logger for module-specific logging', () => {
593
- const appLogger = new ConsoleLogger(
594
- { app: 'myApp', env: 'production' },
595
- LogLevel.Debug,
596
- );
597
- const authLogger = appLogger.child({ module: 'auth' });
598
- const dbLogger = appLogger.child({ module: 'database' });
599
-
600
- authLogger.info({ userId: 123 }, 'User authenticated');
601
- dbLogger.debug({ query: 'SELECT *', duration: 10 }, 'Query executed');
602
-
603
- expect(console.info).toHaveBeenCalledWith({
604
- app: 'myApp',
605
- env: 'production',
606
- module: 'auth',
607
- userId: 123,
608
- msg: 'User authenticated',
609
- ts: 1234567890,
610
- });
611
-
612
- expect(console.debug).toHaveBeenCalledWith({
613
- app: 'myApp',
614
- env: 'production',
615
- module: 'database',
616
- query: 'SELECT *',
617
- duration: 10,
618
- msg: 'Query executed',
619
- ts: 1234567890,
620
- });
621
- });
622
- });
623
-
624
- describe('DEFAULT_LOGGER', () => {
625
- it('should export default logger instance', () => {
626
- const { DEFAULT_LOGGER } = require('../console');
627
-
628
- expect(DEFAULT_LOGGER).toBeDefined();
629
- expect(DEFAULT_LOGGER.data).toBeDefined();
630
- });
631
- });
632
-
633
- describe('createLogger', () => {
634
- it('should create logger with default Info level', () => {
635
- const logger = createLogger();
636
-
637
- logger.debug('This should not appear');
638
- logger.info('This should appear');
639
-
640
- expect(console.debug).not.toHaveBeenCalled();
641
- expect(console.info).toHaveBeenCalled();
642
- });
643
-
644
- it('should create logger with specified level', () => {
645
- const logger = createLogger({ level: LogLevel.Debug });
646
-
647
- logger.trace('This should not appear');
648
- logger.debug('This should appear');
649
-
650
- expect(console.trace).not.toHaveBeenCalled();
651
- expect(console.debug).toHaveBeenCalled();
652
- });
653
-
654
- it('should create silent logger', () => {
655
- const logger = createLogger({ level: LogLevel.Silent });
656
-
657
- logger.error('This should not appear');
658
- logger.fatal('This should not appear');
659
-
660
- expect(console.error).not.toHaveBeenCalled();
661
- });
662
- });
248
+ logger.trace('trace');
249
+ logger.debug('debug');
250
+ logger.info('info');
251
+ logger.warn('warn');
252
+ logger.error('error');
253
+ logger.fatal('fatal');
254
+
255
+ expect(console.trace).not.toHaveBeenCalled();
256
+ expect(console.debug).not.toHaveBeenCalled();
257
+ expect(console.info).not.toHaveBeenCalled();
258
+ expect(console.warn).not.toHaveBeenCalled();
259
+ expect(console.error).not.toHaveBeenCalled();
260
+ });
261
+
262
+ it('should log error when level is Error', () => {
263
+ const logger = new ConsoleLogger({}, LogLevel.Error);
264
+
265
+ logger.info('This should not appear');
266
+ logger.warn('This should not appear');
267
+ logger.error('Error message');
268
+
269
+ expect(console.info).not.toHaveBeenCalled();
270
+ expect(console.warn).not.toHaveBeenCalled();
271
+ expect(console.error).toHaveBeenCalled();
272
+ });
273
+
274
+ it('should inherit log level in child logger', () => {
275
+ const parent = new ConsoleLogger({}, LogLevel.Warn);
276
+ const child = parent.child({ module: 'test' });
277
+
278
+ child.info('This should not appear');
279
+ child.warn('Warning message');
280
+
281
+ expect(console.info).not.toHaveBeenCalled();
282
+ expect(console.warn).toHaveBeenCalled();
283
+ });
284
+ });
285
+
286
+ describe('Context merging', () => {
287
+ it('should merge logger context with log context', () => {
288
+ const logger = new ConsoleLogger({ app: 'myApp', env: 'production' });
289
+
290
+ logger.info({ userId: 123, action: 'login' }, 'User logged in');
291
+
292
+ expect(console.info).toHaveBeenCalledWith({
293
+ app: 'myApp',
294
+ env: 'production',
295
+ userId: 123,
296
+ action: 'login',
297
+ msg: 'User logged in',
298
+ ts: 1234567890,
299
+ });
300
+ });
301
+
302
+ it('should override logger context with log context', () => {
303
+ const logger = new ConsoleLogger({ env: 'production', status: 'old' });
304
+
305
+ logger.info({ status: 'new', userId: 456 }, 'Status updated');
306
+
307
+ expect(console.info).toHaveBeenCalledWith({
308
+ env: 'production',
309
+ status: 'new', // Overridden
310
+ userId: 456,
311
+ msg: 'Status updated',
312
+ ts: 1234567890,
313
+ });
314
+ });
315
+
316
+ it('should always add timestamp', () => {
317
+ const logger = new ConsoleLogger();
318
+
319
+ logger.info({ action: 'test' }, 'Test message');
320
+
321
+ expect(console.info).toHaveBeenCalledWith(
322
+ expect.objectContaining({ ts: 1234567890 }),
323
+ );
324
+ });
325
+ });
326
+
327
+ describe('Additional arguments', () => {
328
+ it('should pass additional arguments to console method', () => {
329
+ const logger = new ConsoleLogger();
330
+ const obj1 = { key: 'value' };
331
+ const obj2 = { another: 'object' };
332
+
333
+ logger.info({ action: 'test' }, 'Message', obj1, obj2);
334
+
335
+ expect(console.info).toHaveBeenCalledWith(
336
+ { action: 'test', msg: 'Message', ts: 1234567890 },
337
+ obj1,
338
+ obj2,
339
+ );
340
+ });
341
+
342
+ it('should pass additional arguments without message', () => {
343
+ const logger = new ConsoleLogger({}, LogLevel.Debug);
344
+ const extra = 'extra data';
345
+
346
+ logger.debug({ action: 'test' }, undefined as any, extra);
347
+
348
+ expect(console.debug).toHaveBeenCalledWith(
349
+ { action: 'test', ts: 1234567890 },
350
+ extra,
351
+ );
352
+ });
353
+ });
354
+
355
+ describe('Child logger', () => {
356
+ it('should create child logger with merged context', () => {
357
+ const parentLogger = new ConsoleLogger({
358
+ app: 'myApp',
359
+ version: '1.0.0',
360
+ });
361
+ const childLogger = parentLogger.child({
362
+ module: 'auth',
363
+ }) as ConsoleLogger;
364
+
365
+ expect(childLogger.data).toEqual({
366
+ app: 'myApp',
367
+ version: '1.0.0',
368
+ module: 'auth',
369
+ });
370
+ });
371
+
372
+ it('should inherit parent context in child logs', () => {
373
+ const parentLogger = new ConsoleLogger({ app: 'myApp' });
374
+ const childLogger = parentLogger.child({ module: 'database' });
375
+
376
+ childLogger.info({ query: 'SELECT *' }, 'Query executed');
377
+
378
+ expect(console.info).toHaveBeenCalledWith({
379
+ app: 'myApp',
380
+ module: 'database',
381
+ query: 'SELECT *',
382
+ msg: 'Query executed',
383
+ ts: 1234567890,
384
+ });
385
+ });
386
+
387
+ it('should override parent context in child logger', () => {
388
+ const parentLogger = new ConsoleLogger({ env: 'dev', status: 'parent' });
389
+ const childLogger = parentLogger.child({
390
+ status: 'child',
391
+ module: 'api',
392
+ }) as ConsoleLogger;
393
+
394
+ expect(childLogger.data).toEqual({
395
+ env: 'dev',
396
+ status: 'child', // Overridden
397
+ module: 'api',
398
+ });
399
+ });
400
+
401
+ it('should create nested child loggers', () => {
402
+ const parentLogger = new ConsoleLogger({ app: 'myApp' });
403
+ const childLogger = parentLogger.child({ module: 'database' });
404
+ const grandchildLogger = childLogger.child({ operation: 'query' });
405
+
406
+ grandchildLogger.info({ table: 'users' }, 'Query executed');
407
+
408
+ expect(console.info).toHaveBeenCalledWith({
409
+ app: 'myApp',
410
+ module: 'database',
411
+ operation: 'query',
412
+ table: 'users',
413
+ msg: 'Query executed',
414
+ ts: 1234567890,
415
+ });
416
+ });
417
+
418
+ it('should not affect parent logger', () => {
419
+ const parentLogger = new ConsoleLogger({ app: 'myApp' });
420
+ const childLogger = parentLogger.child({
421
+ module: 'auth',
422
+ }) as ConsoleLogger;
423
+
424
+ // Child logger has additional context
425
+ expect(childLogger.data).toEqual({ app: 'myApp', module: 'auth' });
426
+
427
+ // Parent logger is unchanged
428
+ expect(parentLogger.data).toEqual({ app: 'myApp' });
429
+ });
430
+ });
431
+
432
+ describe('Edge cases', () => {
433
+ it('should handle string-only logging without context object', () => {
434
+ const logger = new ConsoleLogger({ app: 'test' });
435
+
436
+ logger.info('Simple message without context object');
437
+
438
+ expect(console.info).toHaveBeenCalledWith({
439
+ app: 'test',
440
+ msg: 'Simple message without context object',
441
+ ts: 1234567890,
442
+ });
443
+ });
444
+
445
+ it('should handle string-only logging with child logger', () => {
446
+ const logger = new ConsoleLogger({ app: 'test' });
447
+ const child = logger.child({ module: 'auth' });
448
+
449
+ child.warn('Warning message');
450
+
451
+ expect(console.warn).toHaveBeenCalledWith({
452
+ app: 'test',
453
+ module: 'auth',
454
+ msg: 'Warning message',
455
+ ts: 1234567890,
456
+ });
457
+ });
458
+
459
+ it('should handle empty context object', () => {
460
+ const logger = new ConsoleLogger();
461
+
462
+ logger.info({}, 'Empty context');
463
+
464
+ expect(console.info).toHaveBeenCalledWith({
465
+ msg: 'Empty context',
466
+ ts: 1234567890,
467
+ });
468
+ });
469
+
470
+ it('should handle complex nested objects', () => {
471
+ const logger = new ConsoleLogger();
472
+ const complexObj = {
473
+ user: {
474
+ id: 123,
475
+ profile: {
476
+ name: 'John',
477
+ tags: ['admin', 'user'],
478
+ },
479
+ },
480
+ };
481
+
482
+ logger.info(complexObj, 'Complex object');
483
+
484
+ expect(console.info).toHaveBeenCalledWith({
485
+ ...complexObj,
486
+ msg: 'Complex object',
487
+ ts: 1234567890,
488
+ });
489
+ });
490
+
491
+ it('should handle null and undefined values', () => {
492
+ const logger = new ConsoleLogger();
493
+
494
+ logger.info({ value: null, missing: undefined }, 'Null values');
495
+
496
+ expect(console.info).toHaveBeenCalledWith({
497
+ value: null,
498
+ missing: undefined,
499
+ msg: 'Null values',
500
+ ts: 1234567890,
501
+ });
502
+ });
503
+
504
+ it('should handle special characters in strings', () => {
505
+ const logger = new ConsoleLogger();
506
+
507
+ logger.info({ message: 'Test\n\t"quotes"' }, 'Special chars');
508
+
509
+ expect(console.info).toHaveBeenCalledWith({
510
+ message: 'Test\n\t"quotes"',
511
+ msg: 'Special chars',
512
+ ts: 1234567890,
513
+ });
514
+ });
515
+ });
516
+
517
+ describe('Real-world scenarios', () => {
518
+ it('should log HTTP request', () => {
519
+ const logger = new ConsoleLogger({ service: 'api' });
520
+
521
+ logger.info(
522
+ {
523
+ method: 'POST',
524
+ path: '/users',
525
+ statusCode: 201,
526
+ duration: 45,
527
+ },
528
+ 'HTTP request completed',
529
+ );
530
+
531
+ expect(console.info).toHaveBeenCalledWith({
532
+ service: 'api',
533
+ method: 'POST',
534
+ path: '/users',
535
+ statusCode: 201,
536
+ duration: 45,
537
+ msg: 'HTTP request completed',
538
+ ts: 1234567890,
539
+ });
540
+ });
541
+
542
+ it('should log error with stack trace', () => {
543
+ const logger = new ConsoleLogger({ service: 'worker' });
544
+ const error = new Error('Database connection failed');
545
+
546
+ logger.error(
547
+ {
548
+ error: error.message,
549
+ stack: error.stack,
550
+ operation: 'connect',
551
+ },
552
+ 'Database error',
553
+ );
554
+
555
+ expect(console.error).toHaveBeenCalledWith(
556
+ expect.objectContaining({
557
+ service: 'worker',
558
+ error: 'Database connection failed',
559
+ operation: 'connect',
560
+ msg: 'Database error',
561
+ ts: 1234567890,
562
+ }),
563
+ );
564
+ });
565
+
566
+ it('should log business event', () => {
567
+ const logger = new ConsoleLogger({ app: 'ecommerce' });
568
+
569
+ logger.info(
570
+ {
571
+ eventType: 'order.created',
572
+ orderId: 'ORD-123',
573
+ userId: 456,
574
+ amount: 99.99,
575
+ currency: 'USD',
576
+ },
577
+ 'Order created successfully',
578
+ );
579
+
580
+ expect(console.info).toHaveBeenCalledWith({
581
+ app: 'ecommerce',
582
+ eventType: 'order.created',
583
+ orderId: 'ORD-123',
584
+ userId: 456,
585
+ amount: 99.99,
586
+ currency: 'USD',
587
+ msg: 'Order created successfully',
588
+ ts: 1234567890,
589
+ });
590
+ });
591
+
592
+ it('should use child logger for module-specific logging', () => {
593
+ const appLogger = new ConsoleLogger(
594
+ { app: 'myApp', env: 'production' },
595
+ LogLevel.Debug,
596
+ );
597
+ const authLogger = appLogger.child({ module: 'auth' });
598
+ const dbLogger = appLogger.child({ module: 'database' });
599
+
600
+ authLogger.info({ userId: 123 }, 'User authenticated');
601
+ dbLogger.debug({ query: 'SELECT *', duration: 10 }, 'Query executed');
602
+
603
+ expect(console.info).toHaveBeenCalledWith({
604
+ app: 'myApp',
605
+ env: 'production',
606
+ module: 'auth',
607
+ userId: 123,
608
+ msg: 'User authenticated',
609
+ ts: 1234567890,
610
+ });
611
+
612
+ expect(console.debug).toHaveBeenCalledWith({
613
+ app: 'myApp',
614
+ env: 'production',
615
+ module: 'database',
616
+ query: 'SELECT *',
617
+ duration: 10,
618
+ msg: 'Query executed',
619
+ ts: 1234567890,
620
+ });
621
+ });
622
+ });
623
+
624
+ describe('DEFAULT_LOGGER', () => {
625
+ it('should export default logger instance', () => {
626
+ const { DEFAULT_LOGGER } = require('../console');
627
+
628
+ expect(DEFAULT_LOGGER).toBeDefined();
629
+ expect(DEFAULT_LOGGER.data).toBeDefined();
630
+ });
631
+ });
632
+
633
+ describe('createLogger', () => {
634
+ it('should create logger with default Info level', () => {
635
+ const logger = createLogger();
636
+
637
+ logger.debug('This should not appear');
638
+ logger.info('This should appear');
639
+
640
+ expect(console.debug).not.toHaveBeenCalled();
641
+ expect(console.info).toHaveBeenCalled();
642
+ });
643
+
644
+ it('should create logger with specified level', () => {
645
+ const logger = createLogger({ level: LogLevel.Debug });
646
+
647
+ logger.trace('This should not appear');
648
+ logger.debug('This should appear');
649
+
650
+ expect(console.trace).not.toHaveBeenCalled();
651
+ expect(console.debug).toHaveBeenCalled();
652
+ });
653
+
654
+ it('should create silent logger', () => {
655
+ const logger = createLogger({ level: LogLevel.Silent });
656
+
657
+ logger.error('This should not appear');
658
+ logger.fatal('This should not appear');
659
+
660
+ expect(console.error).not.toHaveBeenCalled();
661
+ });
662
+ });
663
663
  });