@feizk/logger 1.7.0 → 2.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.
package/README.md CHANGED
@@ -1,6 +1,17 @@
1
1
  # @feizk/logger
2
2
 
3
- A simple logger package with colored outputs and timestamps.
3
+ A lightweight, pluggable logger with colored outputs, structured logging, and transport support.
4
+
5
+ ## Features
6
+
7
+ - 🚀 **Zero dependencies** - No external runtime dependencies
8
+ - 🎨 **Colored output** - ANSI color codes for terminal output
9
+ - 📊 **6 log levels** - trace, debug, info, warn, error, fatal
10
+ - 📝 **Structured logging** - JSON mode for production environments
11
+ - 🔌 **Pluggable transports** - Add custom transports (files, databases, etc.)
12
+ - 👶 **Child loggers** - Create prefixed loggers with merged context
13
+ - ⏱️ **Custom timestamps** - Presets (iso, locale) or custom format
14
+ - 🎯 **Type-safe** - Full TypeScript support
4
15
 
5
16
  ## Installation
6
17
 
@@ -15,45 +26,155 @@ import { Logger } from '@feizk/logger';
15
26
 
16
27
  const logger = new Logger();
17
28
 
18
- logger.info('This is an info message');
29
+ logger.info('Hello, world!');
19
30
  logger.warn('This is a warning');
20
31
  logger.error('This is an error');
21
- logger.debug('This is a debug message');
32
+ logger.debug('Debug information');
33
+ logger.trace('Very detailed trace');
34
+ logger.fatal('Critical error!');
22
35
  ```
23
36
 
24
37
  ## Options
25
38
 
26
- | Option | Type | Default | Description |
27
- | --------------- | -------------------------------- | ----------- | ------------------------------------- |
28
- | `enableColors` | `boolean` | `true` | Enable colored output |
29
- | `formatTimestamp`| `function \| undefined` | `ISO format`| Custom timestamp formatter function |
30
- | `formatLog` | `function \| undefined` | `undefined` | Custom log formatter function |
31
- | `level` | `'debug' \| 'info' \| 'warn' \| 'error'` | `'debug'` | Minimum log level |
32
- | `discord` | `object \| undefined` | `undefined` | Discord transport options |
39
+ | Option | Type | Default | Description |
40
+ | -------------- | -------------------------------------------------------------- | ----------- | ---------------------------- |
41
+ | `level` | `'trace' \| 'debug' \| 'info' \| 'warn' \| 'error' \| 'fatal'` | `'debug'` | Minimum log level to output |
42
+ | `silent` | `boolean` | `false` | Suppress all console output |
43
+ | `enableColors` | `boolean` | `true` | Enable colored output |
44
+ | `timestamp` | `'iso' \| 'locale' \| (date: Date) => string` | `'iso'` | Timestamp format |
45
+ | `json` | `boolean` | `false` | Output logs as JSON |
46
+ | `formatter` | `(entry: LogEntry) => string` | `undefined` | Custom log formatter |
47
+ | `transports` | `Transport[]` | `[]` | Initial transports to attach |
48
+ | `prefix` | `string` | `undefined` | Prefix for all log messages |
49
+ | `context` | `Record<string, unknown>` | `{}` | Initial context metadata |
50
+
51
+ ## API
33
52
 
34
- ### Discord Options
53
+ ### Logger Methods
35
54
 
36
- The `discord` option configures Discord webhook integration. It has the following properties:
55
+ - `trace(...args)` - Log a trace message (most verbose)
56
+ - `debug(...args)` - Log a debug message
57
+ - `info(...args)` - Log an info message
58
+ - `warn(...args)` - Log a warning message
59
+ - `error(...args)` - Log an error message
60
+ - `fatal(...args)` - Log a fatal message (most severe)
61
+ - `setLevel(level)` - Set the minimum log level
62
+ - `getLevel()` - Get the current log level
63
+ - `addTransport(transport)` - Add a custom transport
64
+ - `removeTransport(transport)` - Remove a transport
65
+ - `child(options)` - Create a child logger
66
+ - `destroy()` - Destroy the logger and all transports
37
67
 
38
- - `enable`: `boolean`, default `false` - Enable Discord transport
39
- - `webhookURL`: `string`, default `''` - Discord webhook URL
40
- - `formatEmbed`: `function \| undefined`, default `undefined` - Custom embed formatter function
41
- - `batchSize`: `number`, default `10` - Number of embeds per batch request
42
- - `batchDelay`: `number`, default `2000` - Delay in ms between batch sends
43
- - `maxRetries`: `number`, default `3` - Maximum retry attempts for failed sends
44
- - `retryDelayBase`: `number`, default `1000` - Base delay in ms for exponential backoff
68
+ ### Log Levels
45
69
 
46
- ## API
70
+ Logs are filtered by severity. The order from least to most severe:
71
+
72
+ 1. `trace` - Very detailed debugging information
73
+ 2. `debug` - Detailed information for debugging
74
+ 3. `info` - General informational messages
75
+ 4. `warn` - Warning conditions
76
+ 5. `error` - Error conditions
77
+ 6. `fatal` - Critical errors
78
+
79
+ ## Advanced Usage
80
+
81
+ ### Custom Timestamp
82
+
83
+ ```typescript
84
+ const logger = new Logger({
85
+ timestamp: 'locale', // or 'iso' (default)
86
+ });
87
+
88
+ // Custom format
89
+ const logger = new Logger({
90
+ timestamp: (date) => date.toISOString(),
91
+ });
92
+ ```
93
+
94
+ ### Custom Formatter
95
+
96
+ ```typescript
97
+ const logger = new Logger({
98
+ formatter: (entry) =>
99
+ `[${entry.timestamp}] [${entry.level.toUpperCase()}] ${entry.args.join(' ')}`,
100
+ });
101
+ ```
102
+
103
+ ### JSON Structured Logging
104
+
105
+ ```typescript
106
+ const logger = new Logger({ json: true });
107
+ logger.info('User logged in', { userId: '123' });
108
+ // Output: {"level":"info","timestamp":"2024-01-01T00:00:00.000Z","message":"User logged in","context":{"userId":"123"}}
109
+ ```
110
+
111
+ ### Child Logger
112
+
113
+ ```typescript
114
+ const parent = new Logger({ prefix: 'app', context: { version: '1.0.0' } });
47
115
 
48
- ### Logger
116
+ const child = parent.child({
117
+ prefix: 'api',
118
+ context: { endpoint: '/users' },
119
+ });
120
+
121
+ child.info('Request received');
122
+ // Output includes prefix "app:api" and merged context
123
+ ```
124
+
125
+ ### Pluggable Transports
126
+
127
+ ```typescript
128
+ import { Logger, type Transport, type LogEntry } from '@feizk/logger';
129
+
130
+ // Create a custom transport
131
+ class FileTransport implements Transport {
132
+ private stream: WriteStream;
133
+
134
+ constructor(path: string) {
135
+ this.stream = createWriteStream(path);
136
+ }
137
+
138
+ log(entry: LogEntry): void {
139
+ this.stream.write(JSON.stringify(entry) + '\n');
140
+ }
141
+
142
+ destroy(): void {
143
+ this.stream.end();
144
+ }
145
+ }
146
+
147
+ // Use the transport
148
+ const logger = new Logger();
149
+ logger.addTransport(new FileTransport('/var/log/app.log'));
150
+ logger.info('This will be logged to the file');
151
+ ```
152
+
153
+ ## Migration from v1.x
154
+
155
+ ### Discord Transport
156
+
157
+ Discord transport has been moved to a separate package. Use `@feizk/logger-discord` instead:
158
+
159
+ ```typescript
160
+ // v1.x
161
+ const logger = new Logger({
162
+ discord: { enable: true, webhookURL: '...' },
163
+ });
164
+
165
+ // v2.x
166
+ import { Logger } from '@feizk/logger';
167
+ import { DiscordTransport } from '@feizk/logger-discord';
168
+
169
+ const logger = new Logger();
170
+ logger.addTransport(new DiscordTransport({ webhookURL: '...' }));
171
+ ```
49
172
 
50
- - `info(...args: unknown[])`: Logs an info message.
51
- - `warn(...args: unknown[])`: Logs a warning message.
52
- - `error(...args: unknown[])`: Logs an error message.
53
- - `debug(...args: unknown[])`: Logs a debug message.
54
- - `setLevel(level: LogLevel)`: Sets the minimum log level for filtering messages.
173
+ ### Removed Options
55
174
 
56
- All messages include a timestamp and are colored accordingly (unless disabled via options).
175
+ - `discord` - Use `@feizk/logger-discord` instead
176
+ - `formatTimestamp` - Use `timestamp` instead
177
+ - `formatLog` - Use `formatter` instead
57
178
 
58
179
  ## License
59
180
 
package/dist/index.d.mts CHANGED
@@ -1,86 +1,211 @@
1
- type LogLevel = 'debug' | 'info' | 'warn' | 'error';
2
- type TimestampType = 'iso' | 'locale' | 'custom';
3
- interface TimestampTypes {
4
- ISO: 'iso';
5
- Locale: 'locale';
6
- Custom: 'custom';
1
+ /**
2
+ * Log levels ordered by severity.
3
+ * - trace: Very detailed debugging information
4
+ * - debug: Detailed information for debugging
5
+ * - info: General informational messages
6
+ * - warn: Warning conditions
7
+ * - error: Error conditions
8
+ * - fatal: Critical errors that may terminate the application
9
+ */
10
+ type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';
11
+ /**
12
+ * A structured log entry passed to transports and formatters.
13
+ */
14
+ interface LogEntry {
15
+ /** The log level of this entry */
16
+ level: LogLevel;
17
+ /** ISO 8601 formatted timestamp */
18
+ timestamp: string;
19
+ /** Original arguments passed to the log method */
20
+ args: unknown[];
21
+ /** Optional prefix from the logger hierarchy */
22
+ prefix?: string;
23
+ /** Context metadata attached to the logger */
24
+ context: Record<string, unknown>;
7
25
  }
8
- interface DiscordOptions {
9
- enable: boolean;
10
- webhookURL: string;
11
- batchSize?: number;
12
- batchDelay?: number;
13
- maxRetries?: number;
14
- retryDelayBase?: number;
15
- formatEmbed?: (level: LogLevel, timestamp: string, message: string) => Record<string, unknown>;
26
+ /**
27
+ * Pluggable transport interface.
28
+ * Implement this interface to create custom log transports.
29
+ */
30
+ interface Transport {
31
+ /**
32
+ * Called for each log entry.
33
+ * @param entry - The structured log entry
34
+ */
35
+ log(entry: LogEntry): void | Promise<void>;
36
+ /**
37
+ * Optional cleanup method called when the logger is destroyed.
38
+ */
39
+ destroy?(): void | Promise<void>;
16
40
  }
41
+ /**
42
+ * Timestamp option: preset string or custom formatter function.
43
+ * - 'iso': ISO 8601 format (default)
44
+ * - 'locale': Localized date/time string
45
+ * - function: Custom formatter
46
+ */
47
+ type TimestampOption = 'iso' | 'locale' | ((date: Date) => string);
48
+ /**
49
+ * Custom formatter function for log output.
50
+ * @param entry - The structured log entry
51
+ * @returns The formatted string to output to console
52
+ */
53
+ type Formatter = (entry: LogEntry) => string;
54
+ /**
55
+ * Options for creating a child logger.
56
+ */
57
+ interface ChildLoggerOptions {
58
+ /** Prefix to prepend to log messages */
59
+ prefix?: string;
60
+ /** Additional context metadata */
61
+ context?: Record<string, unknown>;
62
+ /** Override log level for this child logger */
63
+ level?: LogLevel;
64
+ /** Override silent mode for this child logger */
65
+ silent?: boolean;
66
+ }
67
+ /**
68
+ * Main logger configuration options.
69
+ */
17
70
  interface LoggerOptions {
71
+ /** Minimum log level to output (default: 'debug') */
18
72
  level?: LogLevel;
73
+ /** Suppress all console output (default: false) */
74
+ silent?: boolean;
75
+ /** Enable colored output (default: true) */
19
76
  enableColors?: boolean;
20
- discord?: DiscordOptions;
21
- formatTimestamp?: (types: TimestampTypes, date?: Date) => [TimestampType, string];
22
- formatLog?: (level: string, timestamp: string, args: unknown[]) => string;
77
+ /** Timestamp format (default: 'iso') */
78
+ timestamp?: TimestampOption;
79
+ /** Custom formatter for log output */
80
+ formatter?: Formatter;
81
+ /** Output logs as JSON (default: false) */
82
+ json?: boolean;
83
+ /** Initial transports to attach */
84
+ transports?: Transport[];
85
+ /** Prefix for all log messages */
86
+ prefix?: string;
87
+ /** Initial context metadata */
88
+ context?: Record<string, unknown>;
23
89
  }
24
90
 
25
91
  /**
26
- * A simple logger with colored outputs and timestamps.
92
+ * A lightweight, pluggable logger with colored outputs, structured logging, and transport support.
93
+ *
94
+ * @example
95
+ * ```typescript
96
+ * import { Logger } from '@feizk/logger';
97
+ *
98
+ * const logger = new Logger();
99
+ *
100
+ * logger.info('Hello, world!');
101
+ * logger.warn('This is a warning');
102
+ * logger.error('This is an error');
103
+ * ```
27
104
  */
28
105
  declare class Logger {
29
- private options;
30
- private level;
31
- private discordQueue;
32
- private isProcessing;
33
- private processTimeout?;
106
+ private readonly options;
107
+ private readonly transports;
108
+ private readonly prefix?;
109
+ private readonly context;
110
+ /**
111
+ * Create a new Logger instance.
112
+ * @param options - Configuration options
113
+ */
34
114
  constructor(options?: LoggerOptions);
35
115
  /**
36
- * Sets the minimum log level for filtering messages.
37
- * @param level - The log level to set.
116
+ * Log a trace message (most verbose).
117
+ * @param args - Arguments to log
118
+ */
119
+ trace(...args: unknown[]): void;
120
+ /**
121
+ * Log a debug message.
122
+ * @param args - Arguments to log
123
+ */
124
+ debug(...args: unknown[]): void;
125
+ /**
126
+ * Log an info message.
127
+ * @param args - Arguments to log
128
+ */
129
+ info(...args: unknown[]): void;
130
+ /**
131
+ * Log a warning message.
132
+ * @param args - Arguments to log
133
+ */
134
+ warn(...args: unknown[]): void;
135
+ /**
136
+ * Log an error message.
137
+ * @param args - Arguments to log
138
+ */
139
+ error(...args: unknown[]): void;
140
+ /**
141
+ * Log a fatal message (most severe).
142
+ * @param args - Arguments to log
143
+ */
144
+ fatal(...args: unknown[]): void;
145
+ /**
146
+ * Set the minimum log level.
147
+ * @param level - The log level to set
38
148
  */
39
149
  setLevel(level: LogLevel): void;
40
150
  /**
41
- * Sends a log message to Discord via webhook if configured.
42
- * @param level - The log level.
43
- * @param timestamp - The formatted timestamp.
44
- * @param args - The log arguments.
151
+ * Get the current log level.
152
+ * @returns The current log level
45
153
  */
46
- private sendToDiscord;
154
+ getLevel(): LogLevel;
47
155
  /**
48
- * Processes the Discord queue by sending batches of embeds.
156
+ * Add a transport to the logger.
157
+ * @param transport - The transport to add
49
158
  */
50
- private processQueue;
159
+ addTransport(transport: Transport): void;
51
160
  /**
52
- * Sends a batch of embeds to Discord.
53
- * @param embeds - The embeds to send.
161
+ * Remove a transport from the logger.
162
+ * @param transport - The transport to remove
54
163
  */
55
- private sendBatch;
164
+ removeTransport(transport: Transport): void;
56
165
  /**
57
- * Checks if a log level should be output based on the current log level.
58
- * @param level - The log level to check.
59
- * @returns True if the message should be logged.
166
+ * Create a child logger with additional prefix and context.
167
+ * @param options - Child logger options
168
+ * @returns A new Logger instance
60
169
  */
61
- private shouldLog;
170
+ child(options?: ChildLoggerOptions): Logger;
62
171
  /**
63
- * Logs an info message.
64
- * @param args - The arguments to log.
172
+ * Destroy the logger and all its transports.
173
+ * Calls destroy() on all registered transports.
65
174
  */
66
- info(...args: unknown[]): void;
175
+ destroy(): Promise<void>;
67
176
  /**
68
- * Logs a warning message.
69
- * @param args - The arguments to log.
177
+ * Core logging method - all public methods delegate here.
178
+ * @param level - The log level
179
+ * @param args - The arguments to log
70
180
  */
71
- warn(...args: unknown[]): void;
181
+ private log;
72
182
  /**
73
- * Logs an error message.
74
- * @param args - The arguments to log.
183
+ * Write a log entry to the console.
184
+ * @param level - The log level
185
+ * @param entry - The log entry
75
186
  */
76
- error(...args: unknown[]): void;
187
+ private writeToConsole;
77
188
  /**
78
- * Logs a debug message.
79
- * @param args - The arguments to log.
189
+ * Dispatch a log entry to a transport.
190
+ * @param transport - The transport
191
+ * @param entry - The log entry
80
192
  */
81
- debug(...args: unknown[]): void;
193
+ private dispatchToTransport;
194
+ /**
195
+ * Check if a log level should be output.
196
+ * @param level - The log level to check
197
+ * @returns True if the message should be logged
198
+ */
199
+ private shouldLog;
82
200
  }
83
201
 
84
- declare const TIMESTAMP_TYPES: TimestampTypes;
202
+ /**
203
+ * Log level priorities ordered by severity (lower = less severe).
204
+ */
205
+ declare const LOG_LEVEL_PRIORITIES: Record<LogLevel, number>;
206
+ /**
207
+ * Text labels for log levels.
208
+ */
209
+ declare const LEVEL_LABELS: Record<LogLevel, string>;
85
210
 
86
- export { type DiscordOptions, type LogLevel, Logger, type LoggerOptions, TIMESTAMP_TYPES, type TimestampType, type TimestampTypes };
211
+ export { type ChildLoggerOptions, type Formatter, LEVEL_LABELS, LOG_LEVEL_PRIORITIES, type LogEntry, type LogLevel, Logger, type LoggerOptions, type TimestampOption, type Transport };