konsole-logger 3.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.
@@ -0,0 +1,605 @@
1
+ export declare class BrowserFormatter implements Formatter {
2
+ write(entry: LogEntry): void;
3
+ }
4
+
5
+ /**
6
+ * A memory-efficient circular buffer for storing logs
7
+ * Automatically evicts oldest entries when capacity is reached
8
+ */
9
+ export declare class CircularBuffer<T> {
10
+ private buffer;
11
+ private head;
12
+ private tail;
13
+ private _size;
14
+ private capacity;
15
+ constructor(capacity: number);
16
+ /**
17
+ * Add an item to the buffer
18
+ * If buffer is full, oldest item is overwritten
19
+ */
20
+ push(item: T): void;
21
+ /**
22
+ * Get all items in order (oldest to newest)
23
+ */
24
+ toArray(): T[];
25
+ /**
26
+ * Get a slice of items
27
+ */
28
+ slice(start: number, end?: number): T[];
29
+ /**
30
+ * Filter items and return matching ones
31
+ */
32
+ filter(predicate: (item: T) => boolean): T[];
33
+ /**
34
+ * Remove items that don't match the predicate
35
+ * Returns the new size
36
+ */
37
+ retain(predicate: (item: T) => boolean): number;
38
+ /**
39
+ * Clear all items
40
+ */
41
+ clear(): void;
42
+ /**
43
+ * Current number of items
44
+ */
45
+ get size(): number;
46
+ /**
47
+ * Check if buffer is empty
48
+ */
49
+ get isEmpty(): boolean;
50
+ /**
51
+ * Check if buffer is at capacity
52
+ */
53
+ get isFull(): boolean;
54
+ }
55
+
56
+ /**
57
+ * Writes log entries to the console / stdout using the formatter pipeline.
58
+ *
59
+ * Primarily useful when the main logger is configured with `format: 'silent'`
60
+ * and you want granular control over what gets printed via separate transports.
61
+ *
62
+ * @example
63
+ * ```ts
64
+ * const logger = new Konsole({
65
+ * namespace: 'App',
66
+ * format: 'silent',
67
+ * transports: [
68
+ * new ConsoleTransport({ format: 'pretty' }),
69
+ * new FileTransport({ path: '/var/log/app.log' }),
70
+ * ],
71
+ * });
72
+ * ```
73
+ */
74
+ export declare class ConsoleTransport implements Transport {
75
+ readonly name: string;
76
+ private formatter;
77
+ private filter?;
78
+ constructor(options?: ConsoleTransportOptions);
79
+ write(entry: LogEntry): void;
80
+ destroy(): Promise<void>;
81
+ }
82
+
83
+ export declare interface ConsoleTransportOptions {
84
+ /** Default: 'console' */
85
+ name?: string;
86
+ /**
87
+ * Output format. Defaults to `'auto'` (pretty on TTY, JSON on non-TTY, browser in browser).
88
+ * Useful when the main logger uses `format: 'silent'` and you want transports
89
+ * to handle all rendering.
90
+ */
91
+ format?: KonsoleFormat;
92
+ /** Only write entries that pass this predicate. */
93
+ filter?: (entry: LogEntry) => boolean;
94
+ }
95
+
96
+ /**
97
+ * Picks the best formatter for the current runtime:
98
+ * browser → BrowserFormatter (styled DevTools output)
99
+ * Node.js + TTY → PrettyFormatter (colorized, human-readable)
100
+ * Node.js + non-TTY → JsonFormatter (newline-delimited JSON)
101
+ */
102
+ export declare function createAutoFormatter(): Formatter;
103
+
104
+ export declare function createFormatter(format: KonsoleFormat): Formatter;
105
+
106
+ /**
107
+ * Fine-grained output filter. Prefer `level` for simple threshold filtering.
108
+ * @deprecated Boolean criteria will be removed in a future version. Use `level` or `format: 'silent'`.
109
+ */
110
+ export declare type Criteria = boolean | ((logEntry: LogEntry) => boolean);
111
+
112
+ export declare type FileFormat = 'json' | 'text';
113
+
114
+ /**
115
+ * Appends log entries as serialized lines to a file on disk.
116
+ *
117
+ * Node.js only. Uses `fs.createWriteStream` internally — efficient for
118
+ * high-throughput logging (writes are buffered by the OS).
119
+ *
120
+ * Entries written before the file handle is opened are buffered in memory
121
+ * and flushed automatically once the stream is ready — no `await ready()`
122
+ * needed for normal use.
123
+ *
124
+ * @example
125
+ * ```ts
126
+ * const logger = new Konsole({
127
+ * namespace: 'App',
128
+ * format: 'pretty', // human-readable in terminal
129
+ * transports: [
130
+ * new FileTransport({ path: '/var/log/app.log' }), // JSON to disk
131
+ * ],
132
+ * });
133
+ * ```
134
+ */
135
+ export declare class FileTransport extends StreamTransport {
136
+ private isReady;
137
+ private pendingEntries;
138
+ private filePath;
139
+ private initialized;
140
+ constructor(options: FileTransportOptions);
141
+ /** Override write to buffer entries until the file stream is open. */
142
+ write(entry: LogEntry): void;
143
+ /**
144
+ * Resolves once the underlying file stream has been opened.
145
+ * Not required for normal use — entries are buffered automatically.
146
+ */
147
+ ready(): Promise<void>;
148
+ private openFile;
149
+ }
150
+
151
+ export declare interface FileTransportOptions {
152
+ /** Absolute or relative path of the log file. */
153
+ path: string;
154
+ /** Default: derived from path, e.g. `'file:/var/log/app.log'` */
155
+ name?: string;
156
+ /**
157
+ * Line format.
158
+ * - `'json'` — newline-delimited JSON (default)
159
+ * - `'text'` — human-readable plain text
160
+ */
161
+ format?: FileFormat;
162
+ /**
163
+ * File open flag passed to `fs.createWriteStream`.
164
+ * - `'a'` — append (default, safe for long-running processes)
165
+ * - `'w'` — truncate on open
166
+ */
167
+ flags?: 'a' | 'w';
168
+ /** Only write entries that pass this predicate. */
169
+ filter?: (entry: LogEntry) => boolean;
170
+ }
171
+
172
+ export declare interface Formatter {
173
+ write(entry: LogEntry): void;
174
+ }
175
+
176
+ /**
177
+ * Resolves the best available `fetch` implementation from the runtime.
178
+ * Returns `undefined` when fetch is not natively available (Node < 18).
179
+ */
180
+ export declare function getGlobalFetch(): typeof fetch | undefined;
181
+
182
+ /**
183
+ * Batches log entries and POSTs them to an HTTP endpoint.
184
+ *
185
+ * Features:
186
+ * - Configurable batch size and flush interval
187
+ * - Exponential-backoff retry on failure
188
+ * - Optional per-entry filter and transform
189
+ * - Works in browser and Node.js ≥ 18 (or pass `fetchImpl` for older Node)
190
+ */
191
+ export declare class HttpTransport implements Transport {
192
+ readonly name: string;
193
+ private config;
194
+ private fetchFn;
195
+ private batch;
196
+ private flushTimer?;
197
+ private retryQueue;
198
+ private isProcessing;
199
+ constructor(config: TransportConfig);
200
+ write(entry: LogEntry): void;
201
+ flush(): Promise<void>;
202
+ destroy(): Promise<void>;
203
+ private sendBatch;
204
+ }
205
+
206
+ /**
207
+ * Runtime environment detection utilities.
208
+ * Use these instead of directly checking `window`, `process`, etc.
209
+ */
210
+ export declare const isBrowser: boolean;
211
+
212
+ export declare const isNode: boolean;
213
+
214
+ /**
215
+ * Returns true when stdout is a TTY (i.e. an interactive terminal).
216
+ * Used to decide whether to enable pretty-printing by default.
217
+ */
218
+ export declare function isTTY(): boolean;
219
+
220
+ export declare function isValidLevel(level: string): level is LogLevelName;
221
+
222
+ export declare class JsonFormatter implements Formatter {
223
+ write(entry: LogEntry): void;
224
+ }
225
+
226
+ /**
227
+ * Konsole — a lightweight, namespaced logging library for browser and Node.js.
228
+ *
229
+ * @example
230
+ * ```ts
231
+ * import { Konsole } from 'konsole-logger';
232
+ *
233
+ * const logger = new Konsole({ namespace: 'API', level: 'info' });
234
+ *
235
+ * logger.info('Server started', { port: 3000 });
236
+ * logger.error('Request failed', { err: new Error('timeout'), path: '/users' });
237
+ * ```
238
+ */
239
+ declare class Konsole implements KonsolePublic {
240
+ private static instances;
241
+ private static globalFlagName;
242
+ private static sharedWorker;
243
+ private static workerPendingCallbacks;
244
+ private logs;
245
+ private namespace;
246
+ private bindings;
247
+ private criteria;
248
+ private formatter;
249
+ private minLevelValue;
250
+ private defaultBatchSize;
251
+ private currentBatchStart;
252
+ private retentionPeriod;
253
+ private maxLogs;
254
+ private cleanupIntervalId?;
255
+ private useWorker;
256
+ private transports;
257
+ constructor(options?: KonsoleOptions);
258
+ /** Retrieve an existing logger by namespace. Creates a new one if not found. */
259
+ static getLogger(namespace?: string): Konsole;
260
+ /** Returns the list of all registered namespace names. */
261
+ static getNamespaces(): string[];
262
+ /**
263
+ * Exposes a `__Konsole` debug handle on `window` for use in browser DevTools.
264
+ *
265
+ * @example
266
+ * ```js
267
+ * // In browser console:
268
+ * __Konsole.getLogger('Auth').viewLogs()
269
+ * __Konsole.listLoggers()
270
+ * __Konsole.enableAll()
271
+ * ```
272
+ */
273
+ static exposeToWindow(): void;
274
+ /**
275
+ * Globally override output for all loggers.
276
+ * `true` — forces all loggers to print regardless of their `level` / `criteria`.
277
+ * `false` — restores normal per-logger rules (default).
278
+ */
279
+ static enableGlobalPrint(enabled: boolean): void;
280
+ /** Add an HTTP transport to every registered logger. */
281
+ static addGlobalTransport(config: TransportConfig): void;
282
+ /**
283
+ * Creates a child logger that inherits this logger's config and prepends
284
+ * `bindings` to every log entry it produces.
285
+ *
286
+ * Bindings accumulate through nested children. Call-site fields always win
287
+ * over bindings on key collision.
288
+ *
289
+ * Children share the parent's circular buffer and formatter.
290
+ * They are NOT registered in `Konsole.instances` — they are ephemeral.
291
+ *
292
+ * @example
293
+ * ```ts
294
+ * // Per-request logger
295
+ * const req = logger.child({ requestId: 'abc', ip: '1.2.3.4' });
296
+ * req.info('request started', { path: '/users' });
297
+ * // → INF [App] request started requestId=abc ip=1.2.3.4 path=/users
298
+ *
299
+ * // Nested child — bindings accumulate
300
+ * const db = req.child({ component: 'db' }, { namespace: 'App:DB' });
301
+ * db.debug('query', { sql: 'SELECT...', ms: 4 });
302
+ * // → DBG [App:DB] query requestId=abc ip=1.2.3.4 component=db sql="SELECT..." ms=4
303
+ * ```
304
+ */
305
+ child(bindings: Record<string, unknown>, options?: KonsoleChildOptions): Konsole;
306
+ /**
307
+ * Factory that bypasses the normal constructor to produce a child logger
308
+ * that shares the parent's buffer, formatter, and transports.
309
+ */
310
+ private static createChild;
311
+ /** Level 10 — extremely verbose, disabled in most environments. */
312
+ trace(...args: unknown[]): void;
313
+ /** Level 20 — developer-facing detail, hidden at `level: 'info'` and above. */
314
+ debug(...args: unknown[]): void;
315
+ /** Level 30 — general informational messages. */
316
+ info(...args: unknown[]): void;
317
+ /** Level 30 — alias for `info()` (backward compatibility). */
318
+ log(...args: unknown[]): void;
319
+ /** Level 40 — something unexpected but recoverable. */
320
+ warn(...args: unknown[]): void;
321
+ /** Level 50 — an operation failed; written to stderr. */
322
+ error(...args: unknown[]): void;
323
+ /** Level 60 — unrecoverable failure; written to stderr. */
324
+ fatal(...args: unknown[]): void;
325
+ /** Update the minimum log level at runtime. */
326
+ setLevel(level: LogLevelName): void;
327
+ /** Update the fine-grained criteria filter. @deprecated Prefer `setLevel()`. */
328
+ setCriteria(criteria: Criteria): void;
329
+ /**
330
+ * Add a transport to this logger.
331
+ * Accepts both a `TransportConfig` plain object (auto-wrapped in `HttpTransport`)
332
+ * and a concrete `Transport` instance (`ConsoleTransport`, `FileTransport`, etc.).
333
+ */
334
+ addTransport(transport: Transport | TransportConfig): void;
335
+ /** Flush all pending transport batches immediately. */
336
+ flushTransports(): Promise<void>;
337
+ /** Print stored logs in batches using `console.table`. Primarily a browser dev tool. */
338
+ viewLogs(batchSize?: number): void;
339
+ /** Returns all stored log entries as a readonly array. */
340
+ getLogs(): ReadonlyArray<LogEntry>;
341
+ /** Returns stored log entries asynchronously (resolves from the worker when `useWorker: true`). */
342
+ getLogsAsync(): Promise<ReadonlyArray<LogEntry>>;
343
+ /** Discard all stored log entries. */
344
+ clearLogs(): void;
345
+ /** Reset the `viewLogs()` pagination cursor back to the beginning. */
346
+ resetBatch(): void;
347
+ /** Returns memory usage statistics for this logger's buffer. */
348
+ getStats(): {
349
+ logCount: number;
350
+ maxLogs: number;
351
+ memoryUsage: string;
352
+ };
353
+ /** Flush transports and remove this logger from the registry. */
354
+ destroy(): Promise<void>;
355
+ /**
356
+ * Parses log call arguments into a structured { msg, fields } pair.
357
+ *
358
+ * Supported calling conventions:
359
+ * logger.info('message') → msg='message', fields={}
360
+ * logger.info('message', { userId: 1 }) → msg='message', fields={userId:1}
361
+ * logger.info({ msg: 'message', userId: 1 }) → msg='message', fields={userId:1} (Pino-style)
362
+ * logger.error(new Error('oops')) → msg='oops', fields={err: Error}
363
+ * logger.info('a', 'b', 'c') → msg='a b c', fields={}
364
+ */
365
+ private parseArgs;
366
+ private addLog;
367
+ private outputLog;
368
+ private initGlobalFlag;
369
+ private flushOldLogs;
370
+ private initWorker;
371
+ private getWorkerCode;
372
+ }
373
+ export { Konsole }
374
+ export default Konsole;
375
+
376
+ /**
377
+ * Options accepted by `logger.child()`.
378
+ */
379
+ export declare interface KonsoleChildOptions {
380
+ /**
381
+ * Override the namespace for this child logger.
382
+ * Useful for labelling a subsystem: `logger.child({}, { namespace: 'App:DB' })`.
383
+ * Defaults to the parent's namespace.
384
+ */
385
+ namespace?: string;
386
+ /**
387
+ * Override the minimum log level for this child.
388
+ * Can only be equal to or more restrictive than the parent — a child cannot
389
+ * log levels that the parent's buffer would discard.
390
+ */
391
+ level?: LogLevelName;
392
+ }
393
+
394
+ export declare type KonsoleFormat = 'auto' | 'pretty' | 'json' | 'text' | 'browser' | 'silent';
395
+
396
+ /**
397
+ * Configuration options for a Konsole logger instance.
398
+ */
399
+ export declare interface KonsoleOptions {
400
+ /** Logger namespace shown in every output line (default: 'Global') */
401
+ namespace?: string;
402
+ /**
403
+ * Minimum log level to process. Entries below this level are discarded
404
+ * immediately — they are neither stored nor output.
405
+ * @default 'trace' (all levels pass through)
406
+ */
407
+ level?: LogLevelName;
408
+ /**
409
+ * Output format.
410
+ * - `'auto'` — selects based on environment (default)
411
+ * - `'pretty'` — colorized, human-readable (Node.js TTY)
412
+ * - `'json'` — newline-delimited JSON (pipes / log aggregators)
413
+ * - `'text'` — plain text, no ANSI (CI / log files)
414
+ * - `'browser'` — styled DevTools output via `%c`
415
+ * - `'silent'` — no output; logs are still stored in memory
416
+ * @default 'auto'
417
+ */
418
+ format?: KonsoleFormat;
419
+ /**
420
+ * Fine-grained output filter or legacy silent flag.
421
+ * @deprecated Boolean `false` — use `format: 'silent'` instead.
422
+ * Boolean `true` — omit this option (auto-output is now the default).
423
+ * Function filter — still fully supported.
424
+ */
425
+ criteria?: Criteria;
426
+ /** Default batch size for `viewLogs()` (default: 100) */
427
+ defaultBatchSize?: number;
428
+ /** How long to keep log entries in ms (default: 48 hours) */
429
+ retentionPeriod?: number;
430
+ /** How often to run the retention cleanup in ms (default: 1 hour) */
431
+ cleanupInterval?: number;
432
+ /** Maximum entries to keep in the circular buffer (default: 10000) */
433
+ maxLogs?: number;
434
+ /** Offload log storage to a Web Worker — browser only (default: false) */
435
+ useWorker?: boolean;
436
+ /**
437
+ * Transports to forward log entries to external destinations.
438
+ * Accepts both `TransportConfig` plain objects (auto-wrapped in `HttpTransport`)
439
+ * and concrete `Transport` instances (`ConsoleTransport`, `FileTransport`, etc.).
440
+ */
441
+ transports?: (Transport | TransportConfig)[];
442
+ }
443
+
444
+ /**
445
+ * Public interface for Konsole logger — safe to expose to untrusted code (e.g. via exposeToWindow).
446
+ */
447
+ export declare interface KonsolePublic {
448
+ viewLogs(batchSize?: number): void;
449
+ }
450
+
451
+ /** 3-character uppercase badge shown in terminal output */
452
+ export declare const LEVEL_LABELS: Record<LogLevelName, string>;
453
+
454
+ export declare const LEVELS: {
455
+ readonly trace: 10;
456
+ readonly debug: 20;
457
+ readonly info: 30;
458
+ readonly warn: 40;
459
+ readonly error: 50;
460
+ readonly fatal: 60;
461
+ };
462
+
463
+ /**
464
+ * Represents a single log entry stored in the circular buffer.
465
+ */
466
+ export declare type LogEntry = {
467
+ /** Primary log message (extracted from the first string argument). */
468
+ msg: string;
469
+ /** All original arguments passed to the log method (kept for backward compatibility). */
470
+ messages: unknown[];
471
+ /** Structured key-value fields merged from the call arguments. */
472
+ fields: Record<string, unknown>;
473
+ timestamp: Date;
474
+ namespace: string;
475
+ level: LogLevelName;
476
+ levelValue: number;
477
+ /** @deprecated Use `level` instead. */
478
+ logtype?: string;
479
+ };
480
+
481
+ export declare type LogLevelName = keyof typeof LEVELS;
482
+
483
+ export declare type LogLevelValue = (typeof LEVELS)[LogLevelName];
484
+
485
+ export declare class PrettyFormatter implements Formatter {
486
+ write(entry: LogEntry): void;
487
+ }
488
+
489
+ export declare class SilentFormatter implements Formatter {
490
+ write(_entry: LogEntry): void;
491
+ }
492
+
493
+ /**
494
+ * Writes log entries as serialized lines into any `WritableLike` stream.
495
+ *
496
+ * Useful for piping logs into HTTP streams, in-memory streams for testing,
497
+ * or any custom writable destination.
498
+ *
499
+ * @example
500
+ * ```ts
501
+ * import { createWriteStream } from 'node:fs';
502
+ *
503
+ * const logger = new Konsole({
504
+ * namespace: 'App',
505
+ * transports: [
506
+ * new StreamTransport({
507
+ * stream: createWriteStream('/tmp/debug.log', { flags: 'a' }),
508
+ * format: 'json',
509
+ * }),
510
+ * ],
511
+ * });
512
+ * ```
513
+ */
514
+ export declare class StreamTransport implements Transport {
515
+ readonly name: string;
516
+ protected stream: WritableLike;
517
+ protected format: FileFormat;
518
+ protected filter?: (entry: LogEntry) => boolean;
519
+ constructor(options: StreamTransportOptions);
520
+ write(entry: LogEntry): void;
521
+ destroy(): Promise<void>;
522
+ }
523
+
524
+ export declare interface StreamTransportOptions {
525
+ /** The writable stream to pipe entries into. */
526
+ stream: WritableLike;
527
+ /** Default: 'stream' */
528
+ name?: string;
529
+ /**
530
+ * Line format written to the stream.
531
+ * - `'json'` — newline-delimited JSON (default, best for log aggregators)
532
+ * - `'text'` — human-readable plain text
533
+ */
534
+ format?: FileFormat;
535
+ /** Only write entries that pass this predicate. */
536
+ filter?: (entry: LogEntry) => boolean;
537
+ }
538
+
539
+ export declare class TextFormatter implements Formatter {
540
+ write(entry: LogEntry): void;
541
+ }
542
+
543
+ /**
544
+ * Base interface all transport implementations must satisfy.
545
+ *
546
+ * A transport receives every log entry that passes the logger's level filter
547
+ * and is responsible for delivering it to some destination (HTTP endpoint,
548
+ * file, stdout, external stream, etc.).
549
+ */
550
+ export declare interface Transport {
551
+ /** Unique identifier used in logs and debug output. */
552
+ readonly name: string;
553
+ /** Called synchronously for each entry that passes all filters. */
554
+ write(entry: LogEntry): void;
555
+ /**
556
+ * Flush any buffered entries.
557
+ * Optional — implement only when the transport batches internally.
558
+ */
559
+ flush?(): Promise<void>;
560
+ /** Flush and release all resources (timers, file handles, sockets). */
561
+ destroy(): Promise<void>;
562
+ }
563
+
564
+ /**
565
+ * Configuration for an HTTP transport that batches and ships logs to an external endpoint.
566
+ */
567
+ export declare interface TransportConfig {
568
+ /** Unique identifier for this transport */
569
+ name: string;
570
+ /** Endpoint URL to POST logs to */
571
+ url: string;
572
+ /** HTTP method (default: POST) */
573
+ method?: 'POST' | 'PUT';
574
+ /** Additional request headers */
575
+ headers?: Record<string, string>;
576
+ /** Number of entries to accumulate before flushing (default: 50) */
577
+ batchSize?: number;
578
+ /** Flush interval in ms (default: 10000) */
579
+ flushInterval?: number;
580
+ /** Retry attempts on failure with exponential backoff (default: 3) */
581
+ retryAttempts?: number;
582
+ /** Only send entries that pass this predicate */
583
+ filter?: (entry: LogEntry) => boolean;
584
+ /** Transform an entry before sending */
585
+ transform?: (entry: LogEntry) => unknown;
586
+ /**
587
+ * Custom fetch implementation.
588
+ * Required on Node.js < 18. Pass e.g. the default export of `node-fetch`.
589
+ * Defaults to `globalThis.fetch`.
590
+ */
591
+ fetchImpl?: typeof fetch;
592
+ }
593
+
594
+ /**
595
+ * Minimal writable-stream contract — duck-typed so it works with Node.js
596
+ * `stream.Writable`, `fs.WriteStream`, and any compatible implementation
597
+ * without requiring `@types/node` in the consumer's project.
598
+ */
599
+ export declare interface WritableLike {
600
+ write(chunk: string): boolean;
601
+ end(cb?: (err?: Error | null) => void): void;
602
+ on(event: 'error', listener: (err: Error) => void): this;
603
+ }
604
+
605
+ export { }