devink 1.0.6 → 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
@@ -9,7 +9,7 @@
9
9
  [![npm version](https://img.shields.io/npm/v/devink.svg)](https://npmjs.org/package/devink)
10
10
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
11
11
 
12
- `devink` is a zero-dependency **Node.js logger** designed for developers who need high performance, beautiful **CLI output**, and structured **JSON logging**. With full **ANSI color support**, dynamic terminal capability detection, and customizable transports, it's the perfect production-ready logger for modern TS/JS environments.
12
+ `devink` is a zero-dependency **Node.js logger** designed for developers who need high performance, beautiful **CLI output**, and structured **JSON logging**. Child loggers, HTTP middleware, file transport with rotation, log sampling, field redaction, pretty error formatting all built in with full **TypeScript** support and **zero external dependencies**.
13
13
 
14
14
  ---
15
15
 
@@ -19,14 +19,22 @@
19
19
 
20
20
  ## 🚀 Features
21
21
 
22
- - **Zero Dependencies**: Lightweight and ultra-fast. No bloated `node_modules`.
23
- - **Full ANSI & 256/RGB Color Support**: Beautiful, soothing UI themes for the terminal. No harsh contrast.
24
- - **Structured JSON Logging**: Instantly switch to JSON mode for seamless integration with Datadog, ELK, AWS CloudWatch, and parsing tools.
25
- - **Log Levels & Priority Filtering**: Granular control via `trace`, `debug`, `info`, `warn`, `error`, and `fatal`.
26
- - **Custom Transports**: Route logs to files, external APIs, or custom formatting engines.
27
- - **Terminal Capability Detection**: Automatically detects `process.stdout.isTTY`, `FORCE_COLOR`, `NO_COLOR`, and `CI` environments.
28
- - **Boxed Output**: Help crucial information stand out with Unicode-boxed messages.
29
- - **TypeScript native**: Built with TS, exporting standard typings out-of-the-box.
22
+ - **Zero Dependencies** Ultra-fast, nothing in `node_modules` except your own code.
23
+ - **Child Loggers** Scoped, namespaced loggers with inherited configuration.
24
+ - **HTTP Middleware** Framework-agnostic request logging for Express, Fastify, Hono, and more.
25
+ - **File Transport with Rotation** Built-in async file transport with size-based rotation and retention.
26
+ - **Log Grouping** Visual grouping for multi-step operations with indented output.
27
+ - **Performance Timers** Measure execution time with `logger.time()` / `logger.timeEnd()`.
28
+ - **Log Sampling / Rate Limiting** Only log a fraction of high-frequency events in production.
29
+ - **Sensitive Field Redaction** Automatically mask passwords, tokens, and secrets from log output.
30
+ - **Pretty Error Formatting** — Colored stack traces with highlighted source locations.
31
+ - **Full ANSI & 256/RGB Color Support** — Beautiful, soothing UI themes for the terminal.
32
+ - **Structured JSON Logging** — One-line switch to JSON for Datadog, ELK, AWS CloudWatch, and more.
33
+ - **Log Levels & Priority Filtering** — Granular control via `trace`, `debug`, `info`, `warn`, `error`, and `fatal`.
34
+ - **Custom Transports** — Route logs to files, external APIs, or custom formatting engines.
35
+ - **Terminal Capability Detection** — Auto-detects `TTY`, `FORCE_COLOR`, `NO_COLOR`, and `CI` environments.
36
+ - **Boxed Output** — Unicode-boxed messages for critical startup and alert information.
37
+ - **TypeScript Native** — Built with TypeScript, full type definitions included.
30
38
 
31
39
  ---
32
40
 
@@ -46,11 +54,9 @@ pnpm add devink
46
54
 
47
55
  ---
48
56
 
49
- ## 💻 Usage
57
+ ## 💻 Quick Start
50
58
 
51
- ### Basic CLI Logger
52
-
53
- Create a beautiful terminal logger with timestamps and the modern theme out of the box:
59
+ ### Basic Logger
54
60
 
55
61
  ```ts
56
62
  import { createLogger } from 'devink';
@@ -71,18 +77,198 @@ logger.error(new Error('Connection timeout'));
71
77
  Perfect for production environments where log aggregation is crucial:
72
78
 
73
79
  ```ts
74
- import { createLogger } from 'devink';
75
-
76
80
  const logger = createLogger({
77
81
  mode: 'json',
78
82
  level: 'trace',
79
83
  });
80
84
 
81
85
  logger.info('Processing payment', { userId: 123, amount: 49.99 });
82
- // Output: {"level":"info","time":"2023-10-25T14:30:00.000Z","message":["Processing payment",{"userId":123,"amount":49.99}]}
86
+ // {"level":"info","time":"2026-03-03T00:00:00.000Z","message":["Processing payment",{"userId":123,"amount":49.99}]}
87
+ ```
88
+
89
+ ---
90
+
91
+ ## Child Loggers / Namespaced Logging
92
+
93
+ Create scoped loggers that inherit the parent configuration and prepend a namespace to every log line:
94
+
95
+ ```ts
96
+ import { createLogger } from 'devink';
97
+
98
+ const logger = createLogger({ timestamps: true });
99
+
100
+ const dbLogger = logger.child({ namespace: 'db' });
101
+ const authLogger = logger.child({ namespace: 'auth' });
102
+
103
+ dbLogger.info('Query executed in 12ms');
104
+ // [14:30:00] [db] ℹ info Query executed in 12ms
105
+
106
+ authLogger.warn('Token expires in 5 minutes');
107
+ // [14:30:00] [auth] ⚠ warn Token expires in 5 minutes
108
+ ```
109
+
110
+ Child loggers can also carry default metadata:
111
+
112
+ ```ts
113
+ const requestLogger = logger.child({ namespace: 'api', requestId: 'abc-123' });
114
+ requestLogger.info('Request received');
115
+ // In JSON mode: {"level":"info","namespace":"api","requestId":"abc-123","message":"Request received"}
116
+ ```
117
+
118
+ ---
119
+
120
+ ## 🌐 HTTP Request Middleware
121
+
122
+ Framework-agnostic middleware that auto-logs every HTTP request with method, path, status code, and response time:
123
+
124
+ ```ts
125
+ import { createLogger, httpMiddleware } from 'devink';
126
+ import express from 'express';
127
+
128
+ const logger = createLogger({ timestamps: true });
129
+ const app = express();
130
+
131
+ app.use(httpMiddleware(logger));
132
+
133
+ // Every request automatically logged:
134
+ // [14:30:05] ℹ info GET /api/users 200 12ms
135
+ // [14:30:06] ⚠ warn POST /api/login 401 8ms
136
+ // [14:30:07] ✖ error GET /api/crash 500 3ms
137
+ ```
138
+
139
+ Works with **Express**, **Fastify**, **Hono**, **Koa**, and any framework using the standard `(req, res, next)` pattern.
140
+
141
+ ---
142
+
143
+ ## 📂 Log Grouping / Indented Sections
144
+
145
+ Visually group related log lines for multi-step operations:
146
+
147
+ ```ts
148
+ const logger = createLogger({ timestamps: true });
149
+
150
+ logger.group('Database Migration');
151
+ logger.info('Running migration 001_create_users...');
152
+ logger.info('Running migration 002_add_indexes...');
153
+ logger.success('All migrations complete');
154
+ logger.groupEnd();
155
+
156
+ logger.info('Server ready');
157
+ ```
158
+
159
+ Output:
160
+
161
+ ```
162
+ [14:30:00] ▸ Database Migration
163
+ [14:30:00] ℹ info Running migration 001_create_users...
164
+ [14:30:01] ℹ info Running migration 002_add_indexes...
165
+ [14:30:01] ✔ success All migrations complete
166
+ [14:30:01] ℹ info Server ready
167
+ ```
168
+
169
+ ---
170
+
171
+ ## ⏱ Performance Timers
172
+
173
+ Measure execution time for any operation directly from the logger:
174
+
175
+ ```ts
176
+ const logger = createLogger();
177
+
178
+ logger.time('database-query');
179
+ await db.query('SELECT * FROM users');
180
+ logger.timeEnd('database-query');
181
+ // ℹ info database-query: 243ms
182
+
183
+ logger.time('api-call');
184
+ await fetch('https://api.example.com/data');
185
+ logger.timeEnd('api-call');
186
+ // ℹ info api-call: 891ms
187
+ ```
188
+
189
+ ---
190
+
191
+ ## 📊 Log Sampling / Rate Limiting
192
+
193
+ In high-throughput production environments, log only a fraction of repetitive events:
194
+
195
+ ```ts
196
+ const logger = createLogger({
197
+ sampling: {
198
+ 'db.query': 0.1, // log 10% of database queries
199
+ 'cache.hit': 0.01, // log 1% of cache hits
200
+ },
201
+ });
202
+
203
+ // Only ~10% of these calls will actually produce output
204
+ logger.info('Query executed', { table: 'users' });
205
+ ```
206
+
207
+ ---
208
+
209
+ ## 📁 Async File Transport
210
+
211
+ Built-in file transport with async writes and automatic log rotation:
212
+
213
+ ```ts
214
+ import { createLogger, FileTransport } from 'devink';
215
+
216
+ const logger = createLogger({
217
+ transports: [
218
+ new FileTransport({
219
+ path: './logs/app.log',
220
+ maxSize: '10mb',
221
+ maxFiles: 5,
222
+ rotate: true,
223
+ }),
224
+ ],
225
+ });
226
+
227
+ logger.info('This goes to a file with automatic rotation');
228
+ ```
229
+
230
+ When `app.log` exceeds 10 MB, it rotates to `app.log.1`, `app.log.2`, etc., keeping at most 5 rotated files.
231
+
232
+ ---
233
+
234
+ ## 🔒 Sensitive Field Redaction
235
+
236
+ Automatically mask sensitive data before it reaches any transport:
237
+
238
+ ```ts
239
+ const logger = createLogger({
240
+ redact: ['password', 'token', 'authorization', 'ssn'],
241
+ });
242
+
243
+ logger.info('User login', { user: 'harry', password: 's3cret!', token: 'eyJhbG...' });
244
+ // ℹ info User login { user: 'harry', password: '[REDACTED]', token: '[REDACTED]' }
83
245
  ```
84
246
 
85
- ### Beautiful Boxed Output
247
+ Redaction works recursively on nested objects and in both text and JSON modes.
248
+
249
+ ---
250
+
251
+ ## 💥 Pretty Error Formatting
252
+
253
+ When you pass an `Error` object, devink renders a beautiful, colored stack trace instead of a raw dump:
254
+
255
+ ```ts
256
+ const logger = createLogger();
257
+
258
+ try {
259
+ throw new Error('Database connection failed');
260
+ } catch (err) {
261
+ logger.error('Fatal error during startup', err);
262
+ }
263
+ ```
264
+
265
+ - Error name and message in **bold red**
266
+ - Your source files highlighted with **colored file paths and line numbers**
267
+ - `node_modules` and Node.js internal frames **dimmed** so your code stands out
268
+
269
+ ---
270
+
271
+ ## 🎁 Boxed Output
86
272
 
87
273
  Make important startup messages or critical alerts pop in the console:
88
274
 
@@ -101,14 +287,17 @@ logger.box(
101
287
 
102
288
  The `createLogger` function accepts an optional `LoggerOptions` object:
103
289
 
104
- | Property | Type | Default | Description |
105
- | ------------ | ------------------ | -------------------- | -------------------------------------------------------------------------------------- |
106
- | `level` | `LogLevelName` | `'trace'` | Minimum log level to output (`trace` < `debug` < `info` < `warn` < `error` < `fatal`). |
107
- | `mode` | `'text' \| 'json'` | `'text'` | Output mode. Text formats for the console, JSON formats for log aggregators. |
108
- | `colors` | `boolean` | `true` | Whether to use ANSI colors. Automatically disabled if terminal doesn't support it. |
109
- | `timestamps` | `boolean` | `false` | Prepend a timestamp to text outputs (`[HH:MM:SS]`). |
110
- | `theme` | `Partial<Theme>` | `modernTheme` | Customize the prefix, success, error, warn, and info styling. |
111
- | `transports` | `Transport[]` | `[ConsoleTransport]` | Target output locations hooks (e.g., standard out, file streams). |
290
+ | Property | Type | Default | Description |
291
+ | ------------ | ------------------------ | -------------------- | ---------------------------------------------------------------------------- |
292
+ | `level` | `LogLevelName` | `'trace'` | Minimum log level (`trace` < `debug` < `info` < `warn` < `error` < `fatal`). |
293
+ | `mode` | `'text' \| 'json'` | `'text'` | Output mode. Text for the console, JSON for log aggregators. |
294
+ | `colors` | `boolean` | `true` | ANSI colors. Automatically disabled if the terminal doesn't support it. |
295
+ | `timestamps` | `boolean` | `false` | Prepend a timestamp (`[HH:MM:SS]`) to text outputs. |
296
+ | `theme` | `Partial<Theme>` | `modernTheme` | Customize prefix icons and color functions for each log level. |
297
+ | `transports` | `Transport[]` | `[ConsoleTransport]` | Target output destinations (console, file, external APIs). |
298
+ | `namespace` | `string` | `''` | Namespace prefix prepended to all log lines. |
299
+ | `redact` | `string[]` | `[]` | Field names to mask with `[REDACTED]` in log output. |
300
+ | `sampling` | `Record<string, number>` | `{}` | Sampling rates (0–1) for rate-limiting high-frequency log events. |
112
301
 
113
302
  ### Theme Presets
114
303
 
@@ -128,28 +317,28 @@ const logger = createLogger({
128
317
 
129
318
  ### Custom Transports
130
319
 
131
- You can easily route logs anywhere by providing objects that implement the `Transport` interface (which requires a `write(ctx: TransportContext)` method).
320
+ Route logs anywhere by implementing the `Transport` interface:
132
321
 
133
322
  ```ts
134
323
  import { createLogger, Transport, TransportContext } from 'devink';
135
324
  import fs from 'node:fs';
136
325
 
137
- class FileTransport implements Transport {
326
+ class CustomTransport implements Transport {
138
327
  write(ctx: TransportContext) {
139
- fs.appendFileSync('app.log', ctx.raw + '\n');
328
+ fs.appendFileSync('custom.log', ctx.raw + '\n');
140
329
  }
141
330
  }
142
331
 
143
332
  const logger = createLogger({
144
- transports: [new FileTransport()], // Now writes to app.log instead of console
333
+ transports: [new CustomTransport()],
145
334
  });
146
335
  ```
147
336
 
148
337
  ---
149
338
 
150
- ## 🎨 ANSI Capabilities
339
+ ## 🎨 ANSI Utilities
151
340
 
152
- If you want to build your own CLI tools, `devink` exports its high-performance, zero-dependency ANSI utilities:
341
+ Build your own CLI tools with devink's high-performance, zero-dependency ANSI utilities:
153
342
 
154
343
  ```ts
155
344
  import { ansi } from 'devink';
@@ -157,11 +346,48 @@ import { ansi } from 'devink';
157
346
  console.log(ansi.rgb(255, 100, 50, 'True RGB text!'));
158
347
  console.log(ansi.hex('#34d399', 'Hex coded text!'));
159
348
  console.log(ansi.color256(128, '256 color terminal support!'));
160
- console.log(ansi.dim('Low contrast subtitle.'));
349
+ console.log(ansi.bold(ansi.cyan('Bold and cyan!')));
161
350
  ```
162
351
 
163
352
  ---
164
353
 
165
- ## 📄 License
354
+ ## 📊 Comparison: devink vs pino vs winston vs bunyan
355
+
356
+ | Feature | devink | pino | winston | bunyan |
357
+ | -------------------------- | ------ | -------------- | -------------- | ------------- |
358
+ | Zero Dependencies | ✅ | ❌ | ❌ | ❌ |
359
+ | TypeScript Native | ✅ | ❌ (types pkg) | ❌ (types pkg) | ❌ |
360
+ | Child Loggers | ✅ | ✅ | ✅ | ✅ |
361
+ | HTTP Middleware (built-in) | ✅ | ❌ (separate) | ❌ (separate) | ❌ |
362
+ | File Transport (built-in) | ✅ | ❌ (separate) | ✅ | ✅ |
363
+ | Log Rotation (built-in) | ✅ | ❌ | ❌ (separate) | ❌ (separate) |
364
+ | Log Sampling | ✅ | ❌ | ❌ | ❌ |
365
+ | Field Redaction | ✅ | ✅ | ❌ | ❌ |
366
+ | Pretty Error Formatting | ✅ | ❌ (separate) | ❌ | ❌ |
367
+ | Log Grouping | ✅ | ❌ | ❌ | ❌ |
368
+ | Performance Timers | ✅ | ❌ | ❌ | ❌ |
369
+ | Colored ANSI Output | ✅ | ❌ (separate) | ❌ (separate) | ❌ |
370
+ | Boxed Output | ✅ | ❌ | ❌ | ❌ |
371
+ | JSON Structured Logging | ✅ | ✅ | ✅ | ✅ |
372
+ | Custom Themes | ✅ | ❌ | ❌ | ❌ |
373
+ | Bundle Size | ~8KB | ~120KB | ~280KB | ~95KB |
374
+
375
+ ---
376
+
377
+ ## 🗺️ Roadmap
378
+
379
+ These features are planned for upcoming releases:
380
+
381
+ - 🌐 **Browser Support** — Universal logger that works in both Node.js and browser DevTools.
382
+ - 🔗 **OpenTelemetry Integration** — Automatic `traceId` and `spanId` injection.
383
+ - 📡 **Log Aggregator Presets** — One-line setup for Datadog, Loki, and Elasticsearch.
384
+ - 🖥️ **Interactive CLI Mode** — Live log panel with filtering for development.
385
+
386
+ ---
387
+
388
+ Built with ❤️ by **[Harry Mate](https://github.com/harrymate22)**.
389
+ 🌟 If you find this library helpful, consider dropping a **Star** on GitHub and **[following me (@harrymate22)](https://github.com/harrymate22)** for more open-source tools!
390
+
391
+ ## License
166
392
 
167
393
  MIT © [harrymate22](https://github.com/harrymate22)
package/dist/index.d.mts CHANGED
@@ -33,6 +33,8 @@ interface TransportContext {
33
33
  formatted: string;
34
34
  raw: string;
35
35
  timestamp: string;
36
+ namespace?: string;
37
+ meta?: Record<string, unknown>;
36
38
  }
37
39
  interface Transport {
38
40
  write(ctx: TransportContext): void;
@@ -44,69 +46,87 @@ interface LoggerOptions {
44
46
  level?: LogLevelName;
45
47
  mode?: 'text' | 'json';
46
48
  transports?: Transport[];
49
+ sampling?: Record<string, number>;
50
+ redact?: string[];
51
+ namespace?: string;
47
52
  }
48
53
  declare class ConsoleTransport implements Transport {
49
54
  write(ctx: TransportContext): void;
50
55
  }
51
56
  declare class Logger {
52
- private theme;
53
- private timestamps;
54
- private colors;
55
- private level;
56
- private mode;
57
- private transports;
58
- private timeCache;
59
- constructor(options?: LoggerOptions);
60
- private shouldLog;
61
- private getTimestamp;
62
- private safeStringify;
63
- private highlightJson;
64
- private formatMessage;
57
+ private t;
58
+ private ts;
59
+ private c;
60
+ private lv;
61
+ private m;
62
+ private tr;
63
+ private tc;
64
+ private sp;
65
+ private rk;
66
+ private ns;
67
+ private gd;
68
+ private tm;
69
+ private sc;
70
+ private dm;
71
+ constructor(opts?: LoggerOptions, meta?: Record<string, unknown>);
72
+ child(bindings: {
73
+ namespace?: string;
74
+ [k: string]: unknown;
75
+ }): Logger;
76
+ group(label: string): void;
77
+ groupEnd(): void;
78
+ time(label: string): void;
79
+ timeEnd(label: string): void;
80
+ private getTs;
81
+ private nsPrefix;
82
+ private hlJson;
83
+ private fmtErr;
84
+ private fmtMsg;
65
85
  private emit;
66
86
  private dispatch;
67
- success(...message: unknown[]): void;
68
- error(...message: unknown[]): void;
69
- warn(...message: unknown[]): void;
70
- info(...message: unknown[]): void;
71
- trace(...message: unknown[]): void;
72
- debug(...message: unknown[]): void;
73
- fatal(...message: unknown[]): void;
87
+ success(...msg: unknown[]): void;
88
+ error(...msg: unknown[]): void;
89
+ warn(...msg: unknown[]): void;
90
+ info(...msg: unknown[]): void;
91
+ trace(...msg: unknown[]): void;
92
+ debug(...msg: unknown[]): void;
93
+ fatal(...msg: unknown[]): void;
74
94
  box(title: string, message: string): void;
75
95
  }
76
- declare const createLogger: (options?: LoggerOptions) => Logger;
96
+ declare const createLogger: (opts?: LoggerOptions) => Logger;
77
97
 
78
98
  declare const isColorSupported: string | boolean;
79
99
  declare const format: (code: number, text: string) => string;
80
- declare const reset: (text: string) => string;
81
- declare const black: (text: string) => string;
82
- declare const red: (text: string) => string;
83
- declare const green: (text: string) => string;
84
- declare const yellow: (text: string) => string;
85
- declare const blue: (text: string) => string;
86
- declare const magenta: (text: string) => string;
87
- declare const cyan: (text: string) => string;
88
- declare const white: (text: string) => string;
89
- declare const gray: (text: string) => string;
90
- declare const bgBlack: (text: string) => string;
91
- declare const bgRed: (text: string) => string;
92
- declare const bgGreen: (text: string) => string;
93
- declare const bgYellow: (text: string) => string;
94
- declare const bgBlue: (text: string) => string;
95
- declare const bgMagenta: (text: string) => string;
96
- declare const bgCyan: (text: string) => string;
97
- declare const bgWhite: (text: string) => string;
98
- declare const bold: (text: string) => string;
99
- declare const dim: (text: string) => string;
100
- declare const italic: (text: string) => string;
101
- declare const underline: (text: string) => string;
102
- declare const inverse: (text: string) => string;
103
- declare const rgb: (r: number, g: number, b: number, text: string) => string;
104
- declare const bgRgb: (r: number, g: number, b: number, text: string) => string;
105
- declare const hex: (hexCode: string, text: string) => string;
106
- declare const bgHex: (hexCode: string, text: string) => string;
107
- declare const color256: (code: number, text: string) => string;
108
- declare const bgColor256: (code: number, text: string) => string;
109
- declare const stripAnsi: (text: string) => string;
100
+ declare const reset: (t: string) => string;
101
+ declare const black: (t: string) => string;
102
+ declare const red: (t: string) => string;
103
+ declare const green: (t: string) => string;
104
+ declare const yellow: (t: string) => string;
105
+ declare const blue: (t: string) => string;
106
+ declare const magenta: (t: string) => string;
107
+ declare const cyan: (t: string) => string;
108
+ declare const white: (t: string) => string;
109
+ declare const gray: (t: string) => string;
110
+ declare const bgBlack: (t: string) => string;
111
+ declare const bgRed: (t: string) => string;
112
+ declare const bgGreen: (t: string) => string;
113
+ declare const bgYellow: (t: string) => string;
114
+ declare const bgBlue: (t: string) => string;
115
+ declare const bgMagenta: (t: string) => string;
116
+ declare const bgCyan: (t: string) => string;
117
+ declare const bgWhite: (t: string) => string;
118
+ declare const bold: (t: string) => string;
119
+ declare const dim: (t: string) => string;
120
+ declare const italic: (t: string) => string;
121
+ declare const underline: (t: string) => string;
122
+ declare const inverse: (t: string) => string;
123
+ declare const rgb: (r: number, g: number, b: number, t: string) => string;
124
+ declare const bgRgb: (r: number, g: number, b: number, t: string) => string;
125
+ declare const hex: (h: string, t: string) => string;
126
+ declare const bgHex: (h: string, t: string) => string;
127
+ declare const color256: (c: number, t: string) => string;
128
+ declare const bgColor256: (c: number, t: string) => string;
129
+ declare const stripAnsi: (t: string) => string;
110
130
 
111
131
  declare const ansi_bgBlack: typeof bgBlack;
112
132
  declare const ansi_bgBlue: typeof bgBlue;
@@ -144,4 +164,29 @@ declare namespace ansi {
144
164
  export { ansi_bgBlack as bgBlack, ansi_bgBlue as bgBlue, ansi_bgColor256 as bgColor256, ansi_bgCyan as bgCyan, ansi_bgGreen as bgGreen, ansi_bgHex as bgHex, ansi_bgMagenta as bgMagenta, ansi_bgRed as bgRed, ansi_bgRgb as bgRgb, ansi_bgWhite as bgWhite, ansi_bgYellow as bgYellow, ansi_black as black, ansi_blue as blue, ansi_bold as bold, ansi_color256 as color256, ansi_cyan as cyan, ansi_dim as dim, ansi_format as format, ansi_gray as gray, ansi_green as green, ansi_hex as hex, ansi_inverse as inverse, ansi_isColorSupported as isColorSupported, ansi_italic as italic, ansi_magenta as magenta, ansi_red as red, ansi_reset as reset, ansi_rgb as rgb, ansi_stripAnsi as stripAnsi, ansi_underline as underline, ansi_white as white, ansi_yellow as yellow };
145
165
  }
146
166
 
147
- export { ConsoleTransport, LogLevel, type LogLevelName, Logger, type LoggerOptions, type Theme, type Transport, type TransportContext, ansi, classicTheme, createLogger, defaultTheme, minimalTheme, modernTheme };
167
+ interface FileTransportOptions {
168
+ path: string;
169
+ maxSize?: string | number;
170
+ maxFiles?: number;
171
+ rotate?: boolean;
172
+ }
173
+ declare class FileTransport implements Transport {
174
+ private fp;
175
+ private ms;
176
+ private mf;
177
+ private rot;
178
+ private sz;
179
+ private q;
180
+ private init;
181
+ constructor(opts: FileTransportOptions);
182
+ write(ctx: TransportContext): void;
183
+ private flush;
184
+ }
185
+
186
+ interface HttpMiddlewareOptions {
187
+ warnAbove?: number;
188
+ errorAbove?: number;
189
+ }
190
+ declare function httpMiddleware(logger: Logger, opts?: HttpMiddlewareOptions): (req: Record<string, unknown>, res: Record<string, unknown>, next: (err?: unknown) => void) => void;
191
+
192
+ export { ConsoleTransport, FileTransport, type FileTransportOptions, type HttpMiddlewareOptions, LogLevel, type LogLevelName, Logger, type LoggerOptions, type Theme, type Transport, type TransportContext, ansi, classicTheme, createLogger, defaultTheme, httpMiddleware, minimalTheme, modernTheme };
package/dist/index.d.ts CHANGED
@@ -33,6 +33,8 @@ interface TransportContext {
33
33
  formatted: string;
34
34
  raw: string;
35
35
  timestamp: string;
36
+ namespace?: string;
37
+ meta?: Record<string, unknown>;
36
38
  }
37
39
  interface Transport {
38
40
  write(ctx: TransportContext): void;
@@ -44,69 +46,87 @@ interface LoggerOptions {
44
46
  level?: LogLevelName;
45
47
  mode?: 'text' | 'json';
46
48
  transports?: Transport[];
49
+ sampling?: Record<string, number>;
50
+ redact?: string[];
51
+ namespace?: string;
47
52
  }
48
53
  declare class ConsoleTransport implements Transport {
49
54
  write(ctx: TransportContext): void;
50
55
  }
51
56
  declare class Logger {
52
- private theme;
53
- private timestamps;
54
- private colors;
55
- private level;
56
- private mode;
57
- private transports;
58
- private timeCache;
59
- constructor(options?: LoggerOptions);
60
- private shouldLog;
61
- private getTimestamp;
62
- private safeStringify;
63
- private highlightJson;
64
- private formatMessage;
57
+ private t;
58
+ private ts;
59
+ private c;
60
+ private lv;
61
+ private m;
62
+ private tr;
63
+ private tc;
64
+ private sp;
65
+ private rk;
66
+ private ns;
67
+ private gd;
68
+ private tm;
69
+ private sc;
70
+ private dm;
71
+ constructor(opts?: LoggerOptions, meta?: Record<string, unknown>);
72
+ child(bindings: {
73
+ namespace?: string;
74
+ [k: string]: unknown;
75
+ }): Logger;
76
+ group(label: string): void;
77
+ groupEnd(): void;
78
+ time(label: string): void;
79
+ timeEnd(label: string): void;
80
+ private getTs;
81
+ private nsPrefix;
82
+ private hlJson;
83
+ private fmtErr;
84
+ private fmtMsg;
65
85
  private emit;
66
86
  private dispatch;
67
- success(...message: unknown[]): void;
68
- error(...message: unknown[]): void;
69
- warn(...message: unknown[]): void;
70
- info(...message: unknown[]): void;
71
- trace(...message: unknown[]): void;
72
- debug(...message: unknown[]): void;
73
- fatal(...message: unknown[]): void;
87
+ success(...msg: unknown[]): void;
88
+ error(...msg: unknown[]): void;
89
+ warn(...msg: unknown[]): void;
90
+ info(...msg: unknown[]): void;
91
+ trace(...msg: unknown[]): void;
92
+ debug(...msg: unknown[]): void;
93
+ fatal(...msg: unknown[]): void;
74
94
  box(title: string, message: string): void;
75
95
  }
76
- declare const createLogger: (options?: LoggerOptions) => Logger;
96
+ declare const createLogger: (opts?: LoggerOptions) => Logger;
77
97
 
78
98
  declare const isColorSupported: string | boolean;
79
99
  declare const format: (code: number, text: string) => string;
80
- declare const reset: (text: string) => string;
81
- declare const black: (text: string) => string;
82
- declare const red: (text: string) => string;
83
- declare const green: (text: string) => string;
84
- declare const yellow: (text: string) => string;
85
- declare const blue: (text: string) => string;
86
- declare const magenta: (text: string) => string;
87
- declare const cyan: (text: string) => string;
88
- declare const white: (text: string) => string;
89
- declare const gray: (text: string) => string;
90
- declare const bgBlack: (text: string) => string;
91
- declare const bgRed: (text: string) => string;
92
- declare const bgGreen: (text: string) => string;
93
- declare const bgYellow: (text: string) => string;
94
- declare const bgBlue: (text: string) => string;
95
- declare const bgMagenta: (text: string) => string;
96
- declare const bgCyan: (text: string) => string;
97
- declare const bgWhite: (text: string) => string;
98
- declare const bold: (text: string) => string;
99
- declare const dim: (text: string) => string;
100
- declare const italic: (text: string) => string;
101
- declare const underline: (text: string) => string;
102
- declare const inverse: (text: string) => string;
103
- declare const rgb: (r: number, g: number, b: number, text: string) => string;
104
- declare const bgRgb: (r: number, g: number, b: number, text: string) => string;
105
- declare const hex: (hexCode: string, text: string) => string;
106
- declare const bgHex: (hexCode: string, text: string) => string;
107
- declare const color256: (code: number, text: string) => string;
108
- declare const bgColor256: (code: number, text: string) => string;
109
- declare const stripAnsi: (text: string) => string;
100
+ declare const reset: (t: string) => string;
101
+ declare const black: (t: string) => string;
102
+ declare const red: (t: string) => string;
103
+ declare const green: (t: string) => string;
104
+ declare const yellow: (t: string) => string;
105
+ declare const blue: (t: string) => string;
106
+ declare const magenta: (t: string) => string;
107
+ declare const cyan: (t: string) => string;
108
+ declare const white: (t: string) => string;
109
+ declare const gray: (t: string) => string;
110
+ declare const bgBlack: (t: string) => string;
111
+ declare const bgRed: (t: string) => string;
112
+ declare const bgGreen: (t: string) => string;
113
+ declare const bgYellow: (t: string) => string;
114
+ declare const bgBlue: (t: string) => string;
115
+ declare const bgMagenta: (t: string) => string;
116
+ declare const bgCyan: (t: string) => string;
117
+ declare const bgWhite: (t: string) => string;
118
+ declare const bold: (t: string) => string;
119
+ declare const dim: (t: string) => string;
120
+ declare const italic: (t: string) => string;
121
+ declare const underline: (t: string) => string;
122
+ declare const inverse: (t: string) => string;
123
+ declare const rgb: (r: number, g: number, b: number, t: string) => string;
124
+ declare const bgRgb: (r: number, g: number, b: number, t: string) => string;
125
+ declare const hex: (h: string, t: string) => string;
126
+ declare const bgHex: (h: string, t: string) => string;
127
+ declare const color256: (c: number, t: string) => string;
128
+ declare const bgColor256: (c: number, t: string) => string;
129
+ declare const stripAnsi: (t: string) => string;
110
130
 
111
131
  declare const ansi_bgBlack: typeof bgBlack;
112
132
  declare const ansi_bgBlue: typeof bgBlue;
@@ -144,4 +164,29 @@ declare namespace ansi {
144
164
  export { ansi_bgBlack as bgBlack, ansi_bgBlue as bgBlue, ansi_bgColor256 as bgColor256, ansi_bgCyan as bgCyan, ansi_bgGreen as bgGreen, ansi_bgHex as bgHex, ansi_bgMagenta as bgMagenta, ansi_bgRed as bgRed, ansi_bgRgb as bgRgb, ansi_bgWhite as bgWhite, ansi_bgYellow as bgYellow, ansi_black as black, ansi_blue as blue, ansi_bold as bold, ansi_color256 as color256, ansi_cyan as cyan, ansi_dim as dim, ansi_format as format, ansi_gray as gray, ansi_green as green, ansi_hex as hex, ansi_inverse as inverse, ansi_isColorSupported as isColorSupported, ansi_italic as italic, ansi_magenta as magenta, ansi_red as red, ansi_reset as reset, ansi_rgb as rgb, ansi_stripAnsi as stripAnsi, ansi_underline as underline, ansi_white as white, ansi_yellow as yellow };
145
165
  }
146
166
 
147
- export { ConsoleTransport, LogLevel, type LogLevelName, Logger, type LoggerOptions, type Theme, type Transport, type TransportContext, ansi, classicTheme, createLogger, defaultTheme, minimalTheme, modernTheme };
167
+ interface FileTransportOptions {
168
+ path: string;
169
+ maxSize?: string | number;
170
+ maxFiles?: number;
171
+ rotate?: boolean;
172
+ }
173
+ declare class FileTransport implements Transport {
174
+ private fp;
175
+ private ms;
176
+ private mf;
177
+ private rot;
178
+ private sz;
179
+ private q;
180
+ private init;
181
+ constructor(opts: FileTransportOptions);
182
+ write(ctx: TransportContext): void;
183
+ private flush;
184
+ }
185
+
186
+ interface HttpMiddlewareOptions {
187
+ warnAbove?: number;
188
+ errorAbove?: number;
189
+ }
190
+ declare function httpMiddleware(logger: Logger, opts?: HttpMiddlewareOptions): (req: Record<string, unknown>, res: Record<string, unknown>, next: (err?: unknown) => void) => void;
191
+
192
+ export { ConsoleTransport, FileTransport, type FileTransportOptions, type HttpMiddlewareOptions, LogLevel, type LogLevelName, Logger, type LoggerOptions, type Theme, type Transport, type TransportContext, ansi, classicTheme, createLogger, defaultTheme, httpMiddleware, minimalTheme, modernTheme };
package/dist/index.js CHANGED
@@ -1,4 +1 @@
1
- 'use strict';var M=Object.defineProperty;var A=(t,r)=>{for(var e in r)M(t,e,{get:r[e],enumerable:true});};var I={};A(I,{bgBlack:()=>F,bgBlue:()=>Y,bgColor256:()=>tt,bgCyan:()=>G,bgGreen:()=>U,bgHex:()=>Q,bgMagenta:()=>D,bgRed:()=>L,bgRgb:()=>R,bgWhite:()=>H,bgYellow:()=>W,black:()=>B,blue:()=>J,bold:()=>P,color256:()=>X,cyan:()=>v,dim:()=>h,format:()=>i,gray:()=>b,green:()=>w,hex:()=>s,inverse:()=>K,isColorSupported:()=>p,italic:()=>Z,magenta:()=>_,red:()=>d,reset:()=>V,rgb:()=>S,stripAnsi:()=>u,underline:()=>q,white:()=>z,yellow:()=>T});var x=process.env,p=!x.NO_COLOR&&(x.FORCE_COLOR||process.stdout&&process.stdout.isTTY||x.TERM==="xterm-256color"||x.CI==="true"),i=(t,r)=>p?`\x1B[${t}m${r}\x1B[0m`:r,V=t=>i(0,t),B=t=>i(30,t),d=t=>i(31,t),w=t=>i(32,t),T=t=>i(33,t),J=t=>i(34,t),_=t=>i(35,t),v=t=>i(36,t),z=t=>i(37,t),b=t=>i(90,t),F=t=>i(40,t),L=t=>i(41,t),U=t=>i(42,t),W=t=>i(43,t),Y=t=>i(44,t),D=t=>i(45,t),G=t=>i(46,t),H=t=>i(47,t),P=t=>i(1,t),h=t=>i(2,t),Z=t=>i(3,t),q=t=>i(4,t),K=t=>i(7,t),S=(t,r,e,o)=>p?`\x1B[38;2;${t};${r};${e}m${o}\x1B[0m`:o,R=(t,r,e,o)=>p?`\x1B[48;2;${t};${r};${e}m${o}\x1B[0m`:o,s=(t,r)=>{if(!p)return r;let e=t.replace(/^#/,"");return e.length!==6?r:S(parseInt(e.slice(0,2),16),parseInt(e.slice(2,4),16),parseInt(e.slice(4,6),16),r)},Q=(t,r)=>{if(!p)return r;let e=t.replace(/^#/,"");return e.length!==6?r:R(parseInt(e.slice(0,2),16),parseInt(e.slice(2,4),16),parseInt(e.slice(4,6),16),r)},X=(t,r)=>p?`\x1B[38;5;${t}m${r}\x1B[0m`:r,tt=(t,r)=>p?`\x1B[48;5;${t}m${r}\x1B[0m`:r,u=t=>t.replace(/\x1b\[[0-9;]*m/g,"");var N={success:t=>s("#10b981",t),error:t=>s("#f43f5e",t),warn:t=>s("#f59e0b",t),info:t=>s("#38bdf8",t),prefix:{success:s("#10b981","\u2714")+" "+s("#34d399",h("success")),error:s("#f43f5e","\u2716")+" "+s("#fb7185",h("error")),warn:s("#f59e0b","\u26A0")+" "+s("#fbbf24",h("warn")),info:s("#38bdf8","\u2139")+" "+s("#7dd3fc",h("info"))}},rt={success:t=>t,error:t=>t,warn:t=>t,info:t=>t,prefix:{success:s("#10b981","\u2714"),error:s("#f43f5e","\u2716"),warn:s("#f59e0b","\u26A0"),info:s("#38bdf8","\u2139")}},et={success:t=>w(t),error:t=>d(t),warn:t=>T(t),info:t=>v(t),prefix:{success:w("SUCCESS"),error:d("ERROR"),warn:T("WARN"),info:v("INFO")}},$=N;var y=(n=>(n[n.trace=10]="trace",n[n.debug=20]="debug",n[n.info=30]="info",n[n.success=35]="success",n[n.warn=40]="warn",n[n.error=50]="error",n[n.fatal=60]="fatal",n[n.none=100]="none",n))(y||{}),C=class{write(r){(r.levelValue>=50?console.error:console.log)(r.formatted);}},k=class{theme;timestamps;colors;level;mode;transports;timeCache={time:"",str:""};constructor(r={}){this.theme={...$,...r.theme,prefix:{...$.prefix,...r.theme?.prefix}},this.timestamps=r.timestamps??false,this.colors=r.colors??!!p,this.level=y[r.level??"trace"],this.mode=r.mode??"text",this.transports=r.transports??[new C];}shouldLog(r){return r>=this.level}getTimestamp(){if(!this.timestamps)return {iso:"",formatted:""};let e=new Date().toISOString(),o=e.split("T")[1]?.split(".")[0]||"";if(this.timeCache.time===o)return {iso:e,formatted:this.timeCache.str};let g=b(`[${o}] `);return this.timeCache={time:o,str:g},{iso:e,formatted:g}}safeStringify(r,e){let o=new Set;return JSON.stringify(r,(g,a)=>{if(typeof a=="object"&&a!==null){if(o.has(a))return "[Circular]";o.add(a);}return a},e)}highlightJson(r){return !this.colors||r.length>5e3?r:r.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g,e=>/^"/.test(e)?/:$/.test(e)?s("#9ca3af",e.slice(0,-1))+":":s("#34d399",e):/true|false/.test(e)?s("#c084fc",e):/null/.test(e)?s("#f87171",e):s("#fbbf24",e))}formatMessage(r){return r.map(e=>{if(typeof e=="string")return e;if(e instanceof Error)return e.stack||e.message;try{return `
2
- `+this.highlightJson(this.safeStringify(e,2))}catch{return "[Unserializable]"}}).join(" ")}emit(r,e,o,g){let a=y[r];if(!this.shouldLog(a))return;let f=this.getTimestamp(),m,n;if(this.mode==="json"){let c={level:r,time:f.iso,message:g.length===1?g[0]:g};m=n=this.safeStringify(c);}else {let c=this.formatMessage(g);m=`${f.formatted}${e} ${o(c)}`,n=u(m),this.colors||(m=n);}this.dispatch(r,a,g,m,n,f.iso);}dispatch(r,e,o,g,a,f){let m={level:r,levelValue:e,message:o,formatted:g,raw:a,timestamp:f};for(let n=0;n<this.transports.length;n++)this.transports[n]?.write(m);}success(...r){this.emit("success",this.theme.prefix.success,this.theme.success,r);}error(...r){this.emit("error",this.theme.prefix.error,this.theme.error,r);}warn(...r){this.emit("warn",this.theme.prefix.warn,this.theme.warn,r);}info(...r){this.emit("info",this.theme.prefix.info,this.theme.info,r);}trace(...r){this.emit("trace",b("\u{1F50D}"),b,r);}debug(...r){this.emit("debug",s("#94a3b8","\u{1F41B}"),e=>s("#94a3b8",e),r);}fatal(...r){this.emit("fatal",s("#be123c","\u{1F480}"),e=>s("#be123c",e),r);}box(r,e){let o=30;if(!this.shouldLog(o))return;let g=e.split(`
3
- `),a=Math.max(r.length,...g.map(l=>u(l).length))+4,f=`\u250C\u2500 ${r} ${"\u2500".repeat(a-r.length-3)}\u2510`,m=`\u2514${"\u2500".repeat(a)}\u2518`,n=g.map(l=>{let E=a-u(l).length-2;return `\u2502 ${l}${" ".repeat(Math.max(0,E))} \u2502`}),c=[f,...n,m].join(`
4
- `),O=u(c);if(this.mode==="json"){let l=this.getTimestamp();c=O=this.safeStringify({level:"info",time:l.iso,title:r,message:e}),this.dispatch("info",o,[e],c,O,l.iso);return}this.colors&&(c=s("#38bdf8",c));let j=this.getTimestamp();this.dispatch("info",o,[e],c,O,j.iso);}},st=t=>new k(t);exports.ConsoleTransport=C;exports.LogLevel=y;exports.Logger=k;exports.ansi=I;exports.classicTheme=et;exports.createLogger=st;exports.defaultTheme=$;exports.minimalTheme=rt;exports.modernTheme=N;
1
+ var t=require("fs/promises"),e=require("fs"),s=require("path"),r=Object.defineProperty,i={};((t,e)=>{for(var s in e)r(t,s,{get:e[s],enumerable:!0})})(i,{bgBlack:()=>w,bgBlue:()=>k,bgColor256:()=>N,bgCyan:()=>j,bgGreen:()=>v,bgHex:()=>I,bgMagenta:()=>O,bgRed:()=>x,bgRgb:()=>L,bgWhite:()=>C,bgYellow:()=>y,black:()=>f,blue:()=>u,bold:()=>E,color256:()=>F,cyan:()=>b,dim:()=>T,format:()=>c,gray:()=>$,green:()=>m,hex:()=>A,inverse:()=>M,isColorSupported:()=>o,italic:()=>S,magenta:()=>d,red:()=>l,reset:()=>h,rgb:()=>R,stripAnsi:()=>q,underline:()=>z,white:()=>g,yellow:()=>p});var n=process.env,o=!n.NO_COLOR&&(n.FORCE_COLOR||process.stdout&&process.stdout.isTTY||"xterm-256color"===n.TERM||"true"===n.CI),a=(t,e)=>o?`[${t}m${e}`:e,c=a,h=t=>a(0,t),f=t=>a(30,t),l=t=>a(31,t),m=t=>a(32,t),p=t=>a(33,t),u=t=>a(34,t),d=t=>a(35,t),b=t=>a(36,t),g=t=>a(37,t),$=t=>a(90,t),w=t=>a(40,t),x=t=>a(41,t),v=t=>a(42,t),y=t=>a(43,t),k=t=>a(44,t),O=t=>a(45,t),j=t=>a(46,t),C=t=>a(47,t),E=t=>a(1,t),T=t=>a(2,t),S=t=>a(3,t),z=t=>a(4,t),M=t=>a(7,t),R=(t,e,s,r)=>o?`[38;2;${t};${e};${s}m${r}`:r,L=(t,e,s,r)=>o?`[48;2;${t};${e};${s}m${r}`:r,A=(t,e)=>{if(!o)return e;const s=t.replace("#","");return 6===s.length?R(parseInt(s.slice(0,2),16),parseInt(s.slice(2,4),16),parseInt(s.slice(4,6),16),e):e},I=(t,e)=>{if(!o)return e;const s=t.replace("#","");return 6===s.length?L(parseInt(s.slice(0,2),16),parseInt(s.slice(2,4),16),parseInt(s.slice(4,6),16),e):e},F=(t,e)=>o?`[38;5;${t}m${e}`:e,N=(t,e)=>o?`[48;5;${t}m${e}`:e,q=t=>t.replace(/\x1b\[[0-9;]*m/g,""),P={success:t=>A("#10b981",t),error:t=>A("#f43f5e",t),warn:t=>A("#f59e0b",t),info:t=>A("#38bdf8",t),prefix:{success:A("#10b981","")+" "+A("#34d399",T("success")),error:A("#f43f5e","")+" "+A("#fb7185",T("error")),warn:A("#f59e0b","")+" "+A("#fbbf24",T("warn")),info:A("#38bdf8","")+" "+A("#7dd3fc",T("info"))}},W={success:t=>t,error:t=>t,warn:t=>t,info:t=>t,prefix:{success:A("#10b981",""),error:A("#f43f5e",""),warn:A("#f59e0b",""),info:A("#38bdf8","")}},B={success:t=>m(t),error:t=>l(t),warn:t=>p(t),info:t=>b(t),prefix:{success:m("SUCCESS"),error:l("ERROR"),warn:p("WARN"),info:b("INFO")}},U=P,D=(t=>(t[t.trace=10]="trace",t[t.debug=20]="debug",t[t.info=30]="info",t[t.success=35]="success",t[t.warn=40]="warn",t[t.error=50]="error",t[t.fatal=60]="fatal",t[t.none=100]="none",t))(D||{}),J=class{write(t){(t.levelValue>=50?console.error:console.log)(t.formatted)}},_={iso:"",formatted:""},V=new Set;function Y(t,e){V.clear();const s=JSON.stringify(t,(t,e)=>{if("object"==typeof e&&null!==e){if(V.has(e))return"[Circular]";V.add(e)}return e},e);return V.clear(),s}function G(t,e){if("object"!=typeof t||null===t||t instanceof Error)return t;if(Array.isArray(t))return t.map(t=>G(t,e));const s={};for(const[r,i]of Object.entries(t))s[r]=e.has(r.toLowerCase())?"[REDACTED]":"object"!=typeof i||null===i||i instanceof Error?i:G(i,e);return s}var H=class t{t;ts;c;lv;m;tr;tc={t:"",s:""};sp;rk;ns;gd=0;tm=new Map;sc=new Map;dm;constructor(t={},e={}){this.t={...U,...t.theme,prefix:{...U.prefix,...t.theme?.prefix}},this.ts=t.timestamps??!1,this.c=t.colors??Boolean(o),this.lv=D[t.level??"trace"],this.m=t.mode??"text",this.tr=t.transports??[new J],this.sp=t.sampling??{},this.rk=new Set((t.redact??[]).map(t=>t.toLowerCase())),this.ns=t.namespace??"",this.dm=e}child(e){const{namespace:s,...r}=e;return new t({theme:this.t,timestamps:this.ts,colors:this.c,level:Object.keys(D).find(t=>D[t]===this.lv),mode:this.m,transports:this.tr,sampling:this.sp,redact:Array.from(this.rk),namespace:s?this.ns?`${this.ns}:${s}`:s:this.ns},{...this.dm,...r})}group(t){if(30<this.lv)return;const e=this.getTs(),s=this.nsPrefix(),r=" ".repeat(this.gd);if("json"===this.m){const s=Y({level:"info",type:"groupStart",label:t,time:e.iso});this.dispatch("info",30,[t],s,s,e.iso)}else{const i=`${e.formatted}${s}${r}${this.c?E(b(`▸ ${t}`)):`▸ ${t}`}`;this.dispatch("info",30,[t],i,q(i),e.iso)}this.gd++}groupEnd(){this.gd>0&&this.gd--}time(t){this.tm.set(t,performance.now())}timeEnd(t){const e=this.tm.get(t);if(void 0===e)return;this.tm.delete(t);const s=performance.now()-e;this.info(`${t}: ${s<1?s.toFixed(3):Math.round(s)}ms`)}getTs(){if(!this.ts)return _;const t=(new Date).toISOString(),e=t.slice(11,19);if(this.tc.t===e)return{iso:t,formatted:this.tc.s};const s=$(`[${e}] `);return this.tc={t:e,s:s},{iso:t,formatted:s}}nsPrefix(){return this.ns?this.c?A("#a78bfa",`[${this.ns}] `):`[${this.ns}] `:""}hlJson(t){return!this.c||t.length>5e3?t:t.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?)/g,t=>'"'===t[0]?t.endsWith(":")?A("#9ca3af",t.slice(0,-1))+":":A("#34d399",t):A("true"===t||"false"===t?"#c084fc":"null"===t?"#f87171":"#fbbf24",t))}fmtErr(t){const e=t.stack||t.message;return this.c?e.split("\n").map((t,e)=>{if(0===e)return E(l(t));const s=t.match(/^(\s+at\s+)(.+?)(\s+\()?(.+?):(\d+):(\d+)\)?$/);return s?s[4].includes("node_modules")||s[4].startsWith("node:")?T(t):`${T(s[1])}${p(s[2])}${T(s[3]||" ")}${b(s[4])}:${A("#fbbf24",s[5])}:${T(s[6])}${s[3]?T(")"):""}`:t.match(/^\s+at\s+/)?T(t):l(t)}).join("\n"):e}fmtMsg(t){return t.map(t=>{if("string"==typeof t)return t;if(t instanceof Error)return"\n"+this.fmtErr(t);try{return"\n"+this.hlJson(Y(this.rk.size?G(t,this.rk):t,2))}catch{return"[Unserializable]"}}).join(" ")}emit(t,e,s,r){const i=D[t];if(i<this.lv)return;const n=this.getTs(),o=this.nsPrefix(),a=" ".repeat(this.gd);let c,h;if("json"===this.m){const e=r.map(t=>"object"!=typeof t||null===t||t instanceof Error||!this.rk.size?t:G(t,this.rk)),s={level:t,time:n.iso,message:1===e.length?e[0]:e};this.ns&&(s.namespace=this.ns),Object.keys(this.dm).length&&Object.assign(s,this.dm),c=h=Y(s)}else c=`${n.formatted}${o}${a}${e} ${s(this.fmtMsg(r))}`,h=q(c),this.c||(c=h);this.dispatch(t,i,r,c,h,n.iso)}dispatch(t,e,s,r,i,n){const o={level:t,levelValue:e,message:s,formatted:r,raw:i,timestamp:n,namespace:this.ns||void 0,meta:Object.keys(this.dm).length?this.dm:void 0};for(let t=0;t<this.tr.length;t++)this.tr[t]?.write(o)}success(...t){this.emit("success",this.t.prefix.success,this.t.success,t)}error(...t){this.emit("error",this.t.prefix.error,this.t.error,t)}warn(...t){this.emit("warn",this.t.prefix.warn,this.t.warn,t)}info(...t){this.emit("info",this.t.prefix.info,this.t.info,t)}trace(...t){this.emit("trace",$("🔍"),$,t)}debug(...t){this.emit("debug",A("#94a3b8","🐛"),t=>A("#94a3b8",t),t)}fatal(...t){this.emit("fatal",A("#be123c","💀"),t=>A("#be123c",t),t)}box(t,e){if(30<this.lv)return;const s=e.split("\n"),r=Math.max(t.length,...s.map(t=>q(t).length))+4,i=`┌─ ${t} ${"─".repeat(r-t.length-3)}┐`,n=`└${"─".repeat(r)}┘`;let o=[i,...s.map(t=>`│ ${t}${" ".repeat(Math.max(0,r-q(t).length-2))} │`),n].join("\n");const a=q(o),c=this.getTs();if("json"===this.m){const s=Y({level:"info",time:c.iso,title:t,message:e});return void this.dispatch("info",30,[e],s,s,c.iso)}this.c&&(o=A("#38bdf8",o)),this.dispatch("info",30,[e],o,a,c.iso)}},K={b:1,kb:1024,mb:1048576,gb:1073741824};exports.ConsoleTransport=J,exports.FileTransport=class{fp;ms;mf;rot;sz=0;q=Promise.resolve();init=!1;constructor(t){this.fp=t.path,this.ms=function(t){if("number"==typeof t)return t;const e=t.trim().toLowerCase().match(/^([\d.]+)\s*(b|kb|mb|gb)?$/);return e?Math.floor(parseFloat(e[1])*K[e[2]||"b"]):10485760}(t.maxSize??"10mb"),this.mf=t.maxFiles??5,this.rot=t.rotate??!0;const r=s.dirname(this.fp);e.existsSync(r)||e.mkdirSync(r,{recursive:!0})}write(t){const e=t.raw+"\n";this.q=this.q.then(()=>this.flush(e))}async flush(e){if(!this.init){try{this.sz=(await t.stat(this.fp)).size}catch{this.sz=0}this.init=!0}const s=Buffer.byteLength(e,"utf8");if(this.rot&&this.sz+s>this.ms){for(let e=this.mf-1;e>=1;e--)try{await t.rename(1===e?this.fp:`${this.fp}.${e-1}`,`${this.fp}.${e}`)}catch{}try{await t.unlink(this.fp)}catch{}this.sz=0}await t.appendFile(this.fp,e,"utf8"),this.sz+=s}},exports.LogLevel=D,exports.Logger=H,exports.ansi=i,exports.classicTheme=B,exports.createLogger=t=>new H(t),exports.defaultTheme=U,exports.httpMiddleware=function(t,e={}){const s=e.warnAbove??400,r=e.errorAbove??500;return(e,i,n)=>{const o=performance.now(),a=e.method??"UNKNOWN",c=e.originalUrl??e.url??"/",h=()=>{const e=Math.round(performance.now()-o),n=i.statusCode??0,h=`${a} ${c} ${n} ${e}ms`;n>=r?t.error(h):n>=s?t.warn(h):t.info(h)},f=i.on,l=i.once;"function"==typeof f?f.call(i,"finish",h):"function"==typeof l&&l.call(i,"close",h),n()}},exports.minimalTheme=W,exports.modernTheme=P;
package/dist/index.mjs CHANGED
@@ -1,4 +1 @@
1
- var M=Object.defineProperty;var A=(t,r)=>{for(var e in r)M(t,e,{get:r[e],enumerable:true});};var I={};A(I,{bgBlack:()=>F,bgBlue:()=>Y,bgColor256:()=>tt,bgCyan:()=>G,bgGreen:()=>U,bgHex:()=>Q,bgMagenta:()=>D,bgRed:()=>L,bgRgb:()=>R,bgWhite:()=>H,bgYellow:()=>W,black:()=>B,blue:()=>J,bold:()=>P,color256:()=>X,cyan:()=>v,dim:()=>h,format:()=>i,gray:()=>b,green:()=>w,hex:()=>s,inverse:()=>K,isColorSupported:()=>p,italic:()=>Z,magenta:()=>_,red:()=>d,reset:()=>V,rgb:()=>S,stripAnsi:()=>u,underline:()=>q,white:()=>z,yellow:()=>T});var x=process.env,p=!x.NO_COLOR&&(x.FORCE_COLOR||process.stdout&&process.stdout.isTTY||x.TERM==="xterm-256color"||x.CI==="true"),i=(t,r)=>p?`\x1B[${t}m${r}\x1B[0m`:r,V=t=>i(0,t),B=t=>i(30,t),d=t=>i(31,t),w=t=>i(32,t),T=t=>i(33,t),J=t=>i(34,t),_=t=>i(35,t),v=t=>i(36,t),z=t=>i(37,t),b=t=>i(90,t),F=t=>i(40,t),L=t=>i(41,t),U=t=>i(42,t),W=t=>i(43,t),Y=t=>i(44,t),D=t=>i(45,t),G=t=>i(46,t),H=t=>i(47,t),P=t=>i(1,t),h=t=>i(2,t),Z=t=>i(3,t),q=t=>i(4,t),K=t=>i(7,t),S=(t,r,e,o)=>p?`\x1B[38;2;${t};${r};${e}m${o}\x1B[0m`:o,R=(t,r,e,o)=>p?`\x1B[48;2;${t};${r};${e}m${o}\x1B[0m`:o,s=(t,r)=>{if(!p)return r;let e=t.replace(/^#/,"");return e.length!==6?r:S(parseInt(e.slice(0,2),16),parseInt(e.slice(2,4),16),parseInt(e.slice(4,6),16),r)},Q=(t,r)=>{if(!p)return r;let e=t.replace(/^#/,"");return e.length!==6?r:R(parseInt(e.slice(0,2),16),parseInt(e.slice(2,4),16),parseInt(e.slice(4,6),16),r)},X=(t,r)=>p?`\x1B[38;5;${t}m${r}\x1B[0m`:r,tt=(t,r)=>p?`\x1B[48;5;${t}m${r}\x1B[0m`:r,u=t=>t.replace(/\x1b\[[0-9;]*m/g,"");var N={success:t=>s("#10b981",t),error:t=>s("#f43f5e",t),warn:t=>s("#f59e0b",t),info:t=>s("#38bdf8",t),prefix:{success:s("#10b981","\u2714")+" "+s("#34d399",h("success")),error:s("#f43f5e","\u2716")+" "+s("#fb7185",h("error")),warn:s("#f59e0b","\u26A0")+" "+s("#fbbf24",h("warn")),info:s("#38bdf8","\u2139")+" "+s("#7dd3fc",h("info"))}},rt={success:t=>t,error:t=>t,warn:t=>t,info:t=>t,prefix:{success:s("#10b981","\u2714"),error:s("#f43f5e","\u2716"),warn:s("#f59e0b","\u26A0"),info:s("#38bdf8","\u2139")}},et={success:t=>w(t),error:t=>d(t),warn:t=>T(t),info:t=>v(t),prefix:{success:w("SUCCESS"),error:d("ERROR"),warn:T("WARN"),info:v("INFO")}},$=N;var y=(n=>(n[n.trace=10]="trace",n[n.debug=20]="debug",n[n.info=30]="info",n[n.success=35]="success",n[n.warn=40]="warn",n[n.error=50]="error",n[n.fatal=60]="fatal",n[n.none=100]="none",n))(y||{}),C=class{write(r){(r.levelValue>=50?console.error:console.log)(r.formatted);}},k=class{theme;timestamps;colors;level;mode;transports;timeCache={time:"",str:""};constructor(r={}){this.theme={...$,...r.theme,prefix:{...$.prefix,...r.theme?.prefix}},this.timestamps=r.timestamps??false,this.colors=r.colors??!!p,this.level=y[r.level??"trace"],this.mode=r.mode??"text",this.transports=r.transports??[new C];}shouldLog(r){return r>=this.level}getTimestamp(){if(!this.timestamps)return {iso:"",formatted:""};let e=new Date().toISOString(),o=e.split("T")[1]?.split(".")[0]||"";if(this.timeCache.time===o)return {iso:e,formatted:this.timeCache.str};let g=b(`[${o}] `);return this.timeCache={time:o,str:g},{iso:e,formatted:g}}safeStringify(r,e){let o=new Set;return JSON.stringify(r,(g,a)=>{if(typeof a=="object"&&a!==null){if(o.has(a))return "[Circular]";o.add(a);}return a},e)}highlightJson(r){return !this.colors||r.length>5e3?r:r.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g,e=>/^"/.test(e)?/:$/.test(e)?s("#9ca3af",e.slice(0,-1))+":":s("#34d399",e):/true|false/.test(e)?s("#c084fc",e):/null/.test(e)?s("#f87171",e):s("#fbbf24",e))}formatMessage(r){return r.map(e=>{if(typeof e=="string")return e;if(e instanceof Error)return e.stack||e.message;try{return `
2
- `+this.highlightJson(this.safeStringify(e,2))}catch{return "[Unserializable]"}}).join(" ")}emit(r,e,o,g){let a=y[r];if(!this.shouldLog(a))return;let f=this.getTimestamp(),m,n;if(this.mode==="json"){let c={level:r,time:f.iso,message:g.length===1?g[0]:g};m=n=this.safeStringify(c);}else {let c=this.formatMessage(g);m=`${f.formatted}${e} ${o(c)}`,n=u(m),this.colors||(m=n);}this.dispatch(r,a,g,m,n,f.iso);}dispatch(r,e,o,g,a,f){let m={level:r,levelValue:e,message:o,formatted:g,raw:a,timestamp:f};for(let n=0;n<this.transports.length;n++)this.transports[n]?.write(m);}success(...r){this.emit("success",this.theme.prefix.success,this.theme.success,r);}error(...r){this.emit("error",this.theme.prefix.error,this.theme.error,r);}warn(...r){this.emit("warn",this.theme.prefix.warn,this.theme.warn,r);}info(...r){this.emit("info",this.theme.prefix.info,this.theme.info,r);}trace(...r){this.emit("trace",b("\u{1F50D}"),b,r);}debug(...r){this.emit("debug",s("#94a3b8","\u{1F41B}"),e=>s("#94a3b8",e),r);}fatal(...r){this.emit("fatal",s("#be123c","\u{1F480}"),e=>s("#be123c",e),r);}box(r,e){let o=30;if(!this.shouldLog(o))return;let g=e.split(`
3
- `),a=Math.max(r.length,...g.map(l=>u(l).length))+4,f=`\u250C\u2500 ${r} ${"\u2500".repeat(a-r.length-3)}\u2510`,m=`\u2514${"\u2500".repeat(a)}\u2518`,n=g.map(l=>{let E=a-u(l).length-2;return `\u2502 ${l}${" ".repeat(Math.max(0,E))} \u2502`}),c=[f,...n,m].join(`
4
- `),O=u(c);if(this.mode==="json"){let l=this.getTimestamp();c=O=this.safeStringify({level:"info",time:l.iso,title:r,message:e}),this.dispatch("info",o,[e],c,O,l.iso);return}this.colors&&(c=s("#38bdf8",c));let j=this.getTimestamp();this.dispatch("info",o,[e],c,O,j.iso);}},st=t=>new k(t);export{C as ConsoleTransport,y as LogLevel,k as Logger,I as ansi,et as classicTheme,st as createLogger,$ as defaultTheme,rt as minimalTheme,N as modernTheme};
1
+ import{stat as t,rename as s,unlink as e,appendFile as r}from"fs/promises";import{existsSync as i,mkdirSync as n}from"fs";import{dirname as o}from"path";var a=Object.defineProperty,c={};((t,s)=>{for(var e in s)a(t,e,{get:s[e],enumerable:!0})})(c,{bgBlack:()=>O,bgBlue:()=>E,bgColor256:()=>U,bgCyan:()=>M,bgGreen:()=>k,bgHex:()=>W,bgMagenta:()=>z,bgRed:()=>j,bgRgb:()=>F,bgWhite:()=>R,bgYellow:()=>C,black:()=>u,blue:()=>$,bold:()=>S,color256:()=>B,cyan:()=>v,dim:()=>A,format:()=>m,gray:()=>x,green:()=>b,hex:()=>P,inverse:()=>N,isColorSupported:()=>f,italic:()=>I,magenta:()=>w,red:()=>d,reset:()=>p,rgb:()=>L,stripAnsi:()=>q,underline:()=>T,white:()=>y,yellow:()=>g});var h=process.env,f=!h.NO_COLOR&&(h.FORCE_COLOR||process.stdout&&process.stdout.isTTY||"xterm-256color"===h.TERM||"true"===h.CI),l=(t,s)=>f?`[${t}m${s}`:s,m=l,p=t=>l(0,t),u=t=>l(30,t),d=t=>l(31,t),b=t=>l(32,t),g=t=>l(33,t),$=t=>l(34,t),w=t=>l(35,t),v=t=>l(36,t),y=t=>l(37,t),x=t=>l(90,t),O=t=>l(40,t),j=t=>l(41,t),k=t=>l(42,t),C=t=>l(43,t),E=t=>l(44,t),z=t=>l(45,t),M=t=>l(46,t),R=t=>l(47,t),S=t=>l(1,t),A=t=>l(2,t),I=t=>l(3,t),T=t=>l(4,t),N=t=>l(7,t),L=(t,s,e,r)=>f?`[38;2;${t};${s};${e}m${r}`:r,F=(t,s,e,r)=>f?`[48;2;${t};${s};${e}m${r}`:r,P=(t,s)=>{if(!f)return s;const e=t.replace("#","");return 6===e.length?L(parseInt(e.slice(0,2),16),parseInt(e.slice(2,4),16),parseInt(e.slice(4,6),16),s):s},W=(t,s)=>{if(!f)return s;const e=t.replace("#","");return 6===e.length?F(parseInt(e.slice(0,2),16),parseInt(e.slice(2,4),16),parseInt(e.slice(4,6),16),s):s},B=(t,s)=>f?`[38;5;${t}m${s}`:s,U=(t,s)=>f?`[48;5;${t}m${s}`:s,q=t=>t.replace(/\x1b\[[0-9;]*m/g,""),D={success:t=>P("#10b981",t),error:t=>P("#f43f5e",t),warn:t=>P("#f59e0b",t),info:t=>P("#38bdf8",t),prefix:{success:P("#10b981","")+" "+P("#34d399",A("success")),error:P("#f43f5e","")+" "+P("#fb7185",A("error")),warn:P("#f59e0b","")+" "+P("#fbbf24",A("warn")),info:P("#38bdf8","")+" "+P("#7dd3fc",A("info"))}},J={success:t=>t,error:t=>t,warn:t=>t,info:t=>t,prefix:{success:P("#10b981",""),error:P("#f43f5e",""),warn:P("#f59e0b",""),info:P("#38bdf8","")}},_={success:t=>b(t),error:t=>d(t),warn:t=>g(t),info:t=>v(t),prefix:{success:b("SUCCESS"),error:d("ERROR"),warn:g("WARN"),info:v("INFO")}},V=D,Y=(t=>(t[t.trace=10]="trace",t[t.debug=20]="debug",t[t.info=30]="info",t[t.success=35]="success",t[t.warn=40]="warn",t[t.error=50]="error",t[t.fatal=60]="fatal",t[t.none=100]="none",t))(Y||{}),G=class{write(t){(t.levelValue>=50?console.error:console.log)(t.formatted)}},H={iso:"",formatted:""},K=new Set;function Z(t,s){K.clear();const e=JSON.stringify(t,(t,s)=>{if("object"==typeof s&&null!==s){if(K.has(s))return"[Circular]";K.add(s)}return s},s);return K.clear(),e}function Q(t,s){if("object"!=typeof t||null===t||t instanceof Error)return t;if(Array.isArray(t))return t.map(t=>Q(t,s));const e={};for(const[r,i]of Object.entries(t))e[r]=s.has(r.toLowerCase())?"[REDACTED]":"object"!=typeof i||null===i||i instanceof Error?i:Q(i,s);return e}var X=class t{t;ts;c;lv;m;tr;tc={t:"",s:""};sp;rk;ns;gd=0;tm=new Map;sc=new Map;dm;constructor(t={},s={}){this.t={...V,...t.theme,prefix:{...V.prefix,...t.theme?.prefix}},this.ts=t.timestamps??!1,this.c=t.colors??Boolean(f),this.lv=Y[t.level??"trace"],this.m=t.mode??"text",this.tr=t.transports??[new G],this.sp=t.sampling??{},this.rk=new Set((t.redact??[]).map(t=>t.toLowerCase())),this.ns=t.namespace??"",this.dm=s}child(s){const{namespace:e,...r}=s;return new t({theme:this.t,timestamps:this.ts,colors:this.c,level:Object.keys(Y).find(t=>Y[t]===this.lv),mode:this.m,transports:this.tr,sampling:this.sp,redact:Array.from(this.rk),namespace:e?this.ns?`${this.ns}:${e}`:e:this.ns},{...this.dm,...r})}group(t){if(30<this.lv)return;const s=this.getTs(),e=this.nsPrefix(),r=" ".repeat(this.gd);if("json"===this.m){const e=Z({level:"info",type:"groupStart",label:t,time:s.iso});this.dispatch("info",30,[t],e,e,s.iso)}else{const i=`${s.formatted}${e}${r}${this.c?S(v(`▸ ${t}`)):`▸ ${t}`}`;this.dispatch("info",30,[t],i,q(i),s.iso)}this.gd++}groupEnd(){this.gd>0&&this.gd--}time(t){this.tm.set(t,performance.now())}timeEnd(t){const s=this.tm.get(t);if(void 0===s)return;this.tm.delete(t);const e=performance.now()-s;this.info(`${t}: ${e<1?e.toFixed(3):Math.round(e)}ms`)}getTs(){if(!this.ts)return H;const t=(new Date).toISOString(),s=t.slice(11,19);if(this.tc.t===s)return{iso:t,formatted:this.tc.s};const e=x(`[${s}] `);return this.tc={t:s,s:e},{iso:t,formatted:e}}nsPrefix(){return this.ns?this.c?P("#a78bfa",`[${this.ns}] `):`[${this.ns}] `:""}hlJson(t){return!this.c||t.length>5e3?t:t.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?)/g,t=>'"'===t[0]?t.endsWith(":")?P("#9ca3af",t.slice(0,-1))+":":P("#34d399",t):P("true"===t||"false"===t?"#c084fc":"null"===t?"#f87171":"#fbbf24",t))}fmtErr(t){const s=t.stack||t.message;return this.c?s.split("\n").map((t,s)=>{if(0===s)return S(d(t));const e=t.match(/^(\s+at\s+)(.+?)(\s+\()?(.+?):(\d+):(\d+)\)?$/);return e?e[4].includes("node_modules")||e[4].startsWith("node:")?A(t):`${A(e[1])}${g(e[2])}${A(e[3]||" ")}${v(e[4])}:${P("#fbbf24",e[5])}:${A(e[6])}${e[3]?A(")"):""}`:t.match(/^\s+at\s+/)?A(t):d(t)}).join("\n"):s}fmtMsg(t){return t.map(t=>{if("string"==typeof t)return t;if(t instanceof Error)return"\n"+this.fmtErr(t);try{return"\n"+this.hlJson(Z(this.rk.size?Q(t,this.rk):t,2))}catch{return"[Unserializable]"}}).join(" ")}emit(t,s,e,r){const i=Y[t];if(i<this.lv)return;const n=this.getTs(),o=this.nsPrefix(),a=" ".repeat(this.gd);let c,h;if("json"===this.m){const s=r.map(t=>"object"!=typeof t||null===t||t instanceof Error||!this.rk.size?t:Q(t,this.rk)),e={level:t,time:n.iso,message:1===s.length?s[0]:s};this.ns&&(e.namespace=this.ns),Object.keys(this.dm).length&&Object.assign(e,this.dm),c=h=Z(e)}else c=`${n.formatted}${o}${a}${s} ${e(this.fmtMsg(r))}`,h=q(c),this.c||(c=h);this.dispatch(t,i,r,c,h,n.iso)}dispatch(t,s,e,r,i,n){const o={level:t,levelValue:s,message:e,formatted:r,raw:i,timestamp:n,namespace:this.ns||void 0,meta:Object.keys(this.dm).length?this.dm:void 0};for(let t=0;t<this.tr.length;t++)this.tr[t]?.write(o)}success(...t){this.emit("success",this.t.prefix.success,this.t.success,t)}error(...t){this.emit("error",this.t.prefix.error,this.t.error,t)}warn(...t){this.emit("warn",this.t.prefix.warn,this.t.warn,t)}info(...t){this.emit("info",this.t.prefix.info,this.t.info,t)}trace(...t){this.emit("trace",x("🔍"),x,t)}debug(...t){this.emit("debug",P("#94a3b8","🐛"),t=>P("#94a3b8",t),t)}fatal(...t){this.emit("fatal",P("#be123c","💀"),t=>P("#be123c",t),t)}box(t,s){if(30<this.lv)return;const e=s.split("\n"),r=Math.max(t.length,...e.map(t=>q(t).length))+4,i=`┌─ ${t} ${"─".repeat(r-t.length-3)}┐`,n=`└${"─".repeat(r)}┘`;let o=[i,...e.map(t=>`│ ${t}${" ".repeat(Math.max(0,r-q(t).length-2))} │`),n].join("\n");const a=q(o),c=this.getTs();if("json"===this.m){const e=Z({level:"info",time:c.iso,title:t,message:s});return void this.dispatch("info",30,[s],e,e,c.iso)}this.c&&(o=P("#38bdf8",o)),this.dispatch("info",30,[s],o,a,c.iso)}},tt=t=>new X(t),st={b:1,kb:1024,mb:1048576,gb:1073741824},et=class{fp;ms;mf;rot;sz=0;q=Promise.resolve();init=!1;constructor(t){this.fp=t.path,this.ms=function(t){if("number"==typeof t)return t;const s=t.trim().toLowerCase().match(/^([\d.]+)\s*(b|kb|mb|gb)?$/);return s?Math.floor(parseFloat(s[1])*st[s[2]||"b"]):10485760}(t.maxSize??"10mb"),this.mf=t.maxFiles??5,this.rot=t.rotate??!0;const s=o(this.fp);i(s)||n(s,{recursive:!0})}write(t){const s=t.raw+"\n";this.q=this.q.then(()=>this.flush(s))}async flush(i){if(!this.init){try{this.sz=(await t(this.fp)).size}catch{this.sz=0}this.init=!0}const n=Buffer.byteLength(i,"utf8");if(this.rot&&this.sz+n>this.ms){for(let t=this.mf-1;t>=1;t--)try{await s(1===t?this.fp:`${this.fp}.${t-1}`,`${this.fp}.${t}`)}catch{}try{await e(this.fp)}catch{}this.sz=0}await r(this.fp,i,"utf8"),this.sz+=n}};function rt(t,s={}){const e=s.warnAbove??400,r=s.errorAbove??500;return(s,i,n)=>{const o=performance.now(),a=s.method??"UNKNOWN",c=s.originalUrl??s.url??"/",h=()=>{const s=Math.round(performance.now()-o),n=i.statusCode??0,h=`${a} ${c} ${n} ${s}ms`;n>=r?t.error(h):n>=e?t.warn(h):t.info(h)},f=i.on,l=i.once;"function"==typeof f?f.call(i,"finish",h):"function"==typeof l&&l.call(i,"close",h),n()}}export{G as ConsoleTransport,et as FileTransport,Y as LogLevel,X as Logger,c as ansi,_ as classicTheme,tt as createLogger,V as defaultTheme,rt as httpMiddleware,J as minimalTheme,D as modernTheme};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "devink",
3
- "version": "1.0.6",
4
- "description": "Fast, lightweight, professional logger built with TypeScript. No dependencies.",
3
+ "version": "2.0.0",
4
+ "description": "Fast, lightweight, professional TypeScript logger with child loggers, HTTP middleware, file transport, log sampling, field redaction, and zero dependencies.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
7
7
  "types": "./dist/index.d.ts",
@@ -30,16 +30,26 @@
30
30
  "prepack": "npm run build"
31
31
  },
32
32
  "keywords": [
33
- "logger",
34
- "logging",
35
- "node-logger",
36
- "typescript-logger",
37
- "terminal-logger",
38
- "ansi-colors",
39
- "cli-logger",
40
- "console-logger",
41
- "structured-logger",
42
- "zero-dependency"
33
+ "logger",
34
+ "logging",
35
+ "node-logger",
36
+ "typescript-logger",
37
+ "terminal-logger",
38
+ "ansi-colors",
39
+ "cli-logger",
40
+ "console-logger",
41
+ "structured-logger",
42
+ "zero-dependency",
43
+ "child-logger",
44
+ "http-middleware",
45
+ "express-logger",
46
+ "file-transport",
47
+ "log-rotation",
48
+ "log-sampling",
49
+ "redact",
50
+ "json-logger",
51
+ "pino-alternative",
52
+ "winston-alternative"
43
53
  ],
44
54
  "author": "harrymate22",
45
55
  "license": "MIT",
@@ -54,6 +64,7 @@
54
64
  "eslint-config-prettier": "^9.1.0",
55
65
  "globals": "^15.0.0",
56
66
  "prettier": "^3.0.0",
67
+ "terser": "^5.46.0",
57
68
  "tsup": "^8.0.0",
58
69
  "typescript": "^5.0.0",
59
70
  "typescript-eslint": "^8.0.0",