logan-logger 2.0.0 โ†’ 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +76 -398
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -4,441 +4,119 @@
4
4
  [![npm](https://img.shields.io/npm/v/logan-logger)](https://www.npmjs.com/package/logan-logger)
5
5
  [![JSR](https://jsr.io/badges/@logan/logger)](https://jsr.io/@logan/logger)
6
6
 
7
- A universal TypeScript logging library that works consistently across all JavaScript runtimes: Node.js, Deno, Bun, browsers, and WebAssembly environments.
7
+ One logging API for Node.js, Deno, Bun and the browser. No dependencies.
8
8
 
9
- > **Upgrading from 1.x?** See the [2.0 migration guide](./docs/migration-2.0.md).
10
- > Winston is gone, file logging is opt-in, and repeated object references are no
11
- > longer reported as `[Circular]`.
12
-
13
- ## Features
14
-
15
- - ๐ŸŒ **Universal Runtime Support** - Works in Node.js, Deno, Bun, browsers, and WebAssembly
16
- - โš›๏ธ **Next.js Ready** - Full compatibility with App Router, Server Components, and API Routes
17
- - ๐Ÿชถ **Zero Dependencies** - No dependencies at all, required or optional, on any runtime
18
- - โšก **Performance First** - Lazy evaluation, zero-allocation logging, minimal memory footprint
19
- - ๐ŸŽฏ **TypeScript Native** - Full type safety with comprehensive type definitions
20
- - ๐Ÿ”ง **Flexible Configuration** - Environment-based auto-configuration or manual setup
21
- - ๐Ÿ”’ **Safe Serialization** - Handles circular references, Error objects, and sensitive data filtering
22
- - ๐ŸŽจ **Rich Browser Support** - Console styling, performance marks, grouping
23
- - ๐Ÿ“Š **Structured Logging** - Rich metadata support with child loggers
24
-
25
- ## Quick Start
26
-
27
- ```bash
28
- # NPM
29
- npm install logan-logger
30
- # or
31
- pnpm add logan-logger
32
- # or
33
- yarn add logan-logger
34
-
35
- # JSR (Deno/Node.js)
36
- deno add @logan/logger
37
- # or
38
- npx jsr add @logan/logger
39
- ```
40
-
41
- ### Basic Usage
42
-
43
- ```typescript
9
+ ```ts
44
10
  import { createLogger, LogLevel } from 'logan-logger';
45
11
 
46
- // Create logger with automatic environment configuration
47
- const logger = createLogger({
48
- level: LogLevel.DEBUG,
49
- colorize: true
50
- });
12
+ const logger = createLogger({ level: LogLevel.DEBUG });
51
13
 
52
- // Basic logging
53
14
  logger.info('Application started');
54
- logger.warn('Configuration missing', { file: 'config.json' });
55
- logger.error('Database connection failed', { error: new Error('Connection failed') });
15
+ logger.warn('Config missing', { file: 'config.json' });
16
+ logger.error('Query failed', { err: new Error('timeout') });
56
17
 
57
- // Child loggers with additional context
58
- const requestLogger = logger.child({
59
- requestId: 'req-123',
60
- userId: 'user-456'
61
- });
18
+ // Context that follows every record, without threading it through your code
19
+ const request = logger.child({ requestId: 'req-123' });
20
+ request.info('Processing', { endpoint: '/api/users' });
62
21
 
63
- requestLogger.info('Processing request', { endpoint: '/api/users' });
22
+ // Costs nothing when the level filters it out - the function is never called
23
+ logger.debug(() => `Expensive: ${computeHeavyValue()}`);
64
24
  ```
65
25
 
66
- Use named imports from `logan-logger` and its runtime subpaths. Default imports
67
- are not part of the public API.
68
-
69
- ### Next.js Integration
70
-
71
- Logan Logger is fully compatible with Next.js 13+ App Router, including Server Components, Client Components, and API Routes.
72
-
73
- #### Server Components
74
- ```typescript
75
- import { createLogger, LogLevel } from 'logan-logger';
76
-
77
- const logger = createLogger({
78
- level: process.env.NODE_ENV === 'development' ? LogLevel.DEBUG : LogLevel.INFO,
79
- format: 'json'
80
- });
81
-
82
- export default async function ServerComponent() {
83
- logger.info('Server component rendered');
84
-
85
- // Server-side data fetching
86
- const data = await fetchData();
87
- logger.debug('Data fetched', { recordCount: data.length });
88
-
89
- return <div>Server content</div>;
90
- }
91
26
  ```
92
-
93
- #### Client Components
94
- ```typescript
95
- 'use client';
96
-
97
- import { createLogger, LogLevel } from 'logan-logger';
98
-
99
- const logger = createLogger({
100
- level: LogLevel.INFO,
101
- colorize: true
102
- });
103
-
104
- export default function ClientComponent() {
105
- const handleClick = () => {
106
- logger.info('User interaction', { action: 'button_click' });
107
- };
108
-
109
- return <button onClick={handleClick}>Click me</button>;
110
- }
111
- ```
112
-
113
- #### API Routes
114
- ```typescript
115
- // app/api/users/route.ts
116
- import { NextResponse } from 'next/server';
117
- import { createLogger } from 'logan-logger';
118
-
119
- const logger = createLogger({
120
- format: 'json',
121
- metadata: { service: 'api' }
122
- });
123
-
124
- export async function GET() {
125
- const start = Date.now();
126
- logger.info('API request started', { endpoint: '/api/users' });
127
-
128
- try {
129
- const users = await getUsers();
130
- const duration = Date.now() - start;
131
-
132
- logger.info('API request completed', {
133
- statusCode: 200,
134
- duration,
135
- userCount: users.length
136
- });
137
-
138
- return NextResponse.json(users);
139
- } catch (error) {
140
- const duration = Date.now() - start;
141
- logger.error('API request failed', {
142
- statusCode: 500,
143
- duration,
144
- error: error instanceof Error ? error.message : 'Unknown error'
145
- });
146
-
147
- return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 });
148
- }
149
- }
150
- ```
151
-
152
- > **๐Ÿ“‹ See [Next.js Compatibility Guide](./docs/nextjs-compatibility.md) for complete setup instructions, advanced patterns, and troubleshooting.**
153
-
154
- ### Advanced Features
155
-
156
- #### Lazy Evaluation for Performance
157
- ```typescript
158
- // Function is only called if debug level is enabled
159
- logger.debug(() => `Expensive computation: ${computeHeavyValue()}`);
160
- ```
161
-
162
- #### Environment-Based Configuration
163
- ```typescript
164
- import { createLoggerForEnvironment } from 'logan-logger';
165
-
166
- // Automatically configures based on NODE_ENV
167
- const logger = createLoggerForEnvironment();
168
- // Production: ERROR level, JSON format
169
- // Development: DEBUG level, colored console
170
- // Test: WARN level
27
+ [2026-08-22T16:31:25.870Z] INFO: Application started
28
+ [2026-08-22T16:31:25.871Z] WARN: Config missing {"file":"config.json"}
29
+ [2026-08-22T16:31:25.872Z] ERROR: Query failed {"err":{"name":"Error","message":"timeout","stack":"..."}}
30
+ [2026-08-22T16:31:25.873Z] INFO: Processing {"requestId":"req-123","endpoint":"/api/users"}
171
31
  ```
172
32
 
173
- #### Runtime-Specific Imports
174
-
175
- Logan Logger provides runtime-specific entry points for optimal bundling and type safety:
33
+ Switch to `format: 'json'` and the same calls emit a structured envelope your log
34
+ aggregator can parse.
176
35
 
177
- **๐ŸŸข Node.js with file logging:**
178
- ```typescript
179
- import { createLogger, LogLevel, NodeLogger, createMorganStream } from 'logan-logger/node';
180
-
181
- const logger = new NodeLogger({
182
- transports: [
183
- { type: 'console', options: {} },
184
- {
185
- type: 'file',
186
- level: LogLevel.ERROR,
187
- options: { filename: 'logs/error.log', maxsize: 5_242_880, maxFiles: 5 }
188
- }
189
- ]
190
- });
191
-
192
- // Express/Morgan integration
193
- app.use(morgan('combined', { stream: createMorganStream(logger) }));
194
- ```
36
+ ## Why this one
195
37
 
196
- File logging is **opt-in**: with no `transports` configured a logger writes to the
197
- console and nowhere else, whatever `NODE_ENV` says. The log directory is created
198
- lazily on the first write, so a logger that is configured but never used touches
199
- the disk zero times.
38
+ - **No dependencies.** Not "few" โ€” `dependencies` and `peerDependencies` are both
39
+ empty in the published package.
40
+ - **The same code runs everywhere.** One import, one API. The library detects
41
+ Node, Deno, Bun, the browser or a web worker and picks an implementation.
42
+ - **Browser-safe by construction.** The main entry contains no `node:` specifier
43
+ at all, so bundling it for the browser cannot fail on an unresolvable built-in.
44
+ That is enforced by where the code lives, not by a bundler shim.
45
+ - **Serialization that does not lose your data.** Circular references, `Error`
46
+ objects with their own properties, `BigInt`, `Symbol`, functions and deep
47
+ nesting all survive โ€” as markers where they must, in full where they can.
48
+ - **TypeScript native**, with correct ESM and CJS types on every entry point.
200
49
 
201
- The `file` transport is registered by the `logan-logger/node` and
202
- `logan-logger/bun` entry points. It is deliberately absent from the main
203
- `logan-logger` entry so that `node:fs` never reaches a browser bundle โ€” configure
204
- a file transport from the main entry and you get a warning telling you which
205
- entry point to import instead.
50
+ ## Install
206
51
 
207
- **๐ŸŒ Browser-Optimized (Webpack/Vite-Safe):**
208
- ```typescript
209
- import { createLogger, BrowserLogger, PerformanceLogger } from 'logan-logger/browser';
210
-
211
- const logger = new PerformanceLogger();
212
-
213
- logger.mark('api-start');
214
- // ... API call
215
- logger.measure('api-duration', 'api-start');
216
- ```
217
-
218
- **๐Ÿฆ• Deno-Optimized:**
219
- ```typescript
220
- import { createLogger, BrowserLogger } from 'logan-logger/deno';
221
-
222
- const logger = createLogger({ colorize: true });
223
- logger.info('Deno application started');
224
- ```
225
-
226
- **๐ŸฅŸ Bun-Optimized:**
227
- ```typescript
228
- import { createLogger, NodeLogger } from 'logan-logger/bun';
229
-
230
- const logger = createLogger({ level: LogLevel.DEBUG });
231
- logger.info('Bun application started');
232
- ```
233
-
234
- **๐Ÿ”ง Auto-Detection (Generic):**
235
- ```typescript
236
- import { createLogger } from 'logan-logger';
237
-
238
- // Automatically selects appropriate logger based on runtime
239
- const logger = createLogger();
240
- ```
241
-
242
- #### Safe Data Handling
243
- ```typescript
244
- import { filterSensitiveData } from 'logan-logger';
245
-
246
- const userData = {
247
- name: 'John Doe',
248
- email: 'john@example.com',
249
- password: 'secret123', // Will be filtered
250
- apiKey: 'sk_live_...' // Will be filtered
251
- };
252
-
253
- const safeData = filterSensitiveData(userData);
254
- logger.info('User processed', safeData);
255
- // Logs: { name: 'John Doe', email: 'john@example.com', password: '[REDACTED]', apiKey: '[REDACTED]' }
256
- ```
257
-
258
- ## Runtime Support & Import Paths
259
-
260
- | Runtime | Import Path | Status | Implementation | Features |
261
- |---------|-------------|--------|----------------|----------|
262
- | **Next.js 13+** | `logan-logger` | โœ… **Full** | **Auto-detection** | **Server/Client Components, API Routes, Edge Runtime** |
263
- | Node.js 20+ | `logan-logger/node` | โœ… Full | Console + File transports | File logging with size rotation, custom transports, Morgan integration |
264
- | Bun | `logan-logger/bun` | โœ… Full | NodeLogger adapter | Same as Node.js |
265
- | Browser | `logan-logger/browser` | โœ… Full | Console API | CSS styling, performance marks, grouping |
266
- | Deno | `@logan/logger/deno` (JSR) | โœ… Basic | BrowserLogger adapter | Console logging (native implementation planned) |
267
- | WebWorker | `logan-logger/browser` | โœ… Basic | Console adapter | Basic console logging |
268
- | Auto-detect | `logan-logger` | โœ… Basic | Runtime detection | Automatic adapter selection |
269
-
270
- ## Configuration
271
-
272
- ### Log Levels
273
- ```typescript
274
- enum LogLevel {
275
- DEBUG = 0, // Most verbose
276
- INFO = 1, // General information
277
- WARN = 2, // Warning messages
278
- ERROR = 3, // Error messages
279
- SILENT = 4 // No output
280
- }
281
- ```
282
-
283
- ### Environment Variables
284
52
  ```bash
285
- LOG_LEVEL=debug # debug, info, warn, error, silent
286
- LOG_FORMAT=json # json, text
287
- LOG_TIMESTAMP=true # true/1/yes/on, false/0/no/off
288
- LOG_COLOR=false # true/1/yes/on, false/0/no/off
53
+ npm install logan-logger # or pnpm add / yarn add
54
+ deno add jsr:@logan/logger # or npx jsr add @logan/logger
289
55
  ```
290
56
 
291
- These sit at the **top** of the precedence chain โ€” above configuration passed to
292
- `createLogger()` โ€” so an operator can change logging on a running service without
293
- a deploy. Opt out with `createLogger({ ..., ignoreEnvironment: true })`. A value
294
- that does not parse is ignored with a warning rather than silently resolving to a
295
- default.
296
-
297
- > **๐Ÿ“‹ See [Environment Variables Documentation](./docs/environment-variables.md) for complete details, examples, and runtime-specific considerations.**
298
-
299
- ### Configuration Options
300
- ```typescript
301
- interface LoggerConfig {
302
- level: LogLevel;
303
- format: 'json' | 'text' | 'custom';
304
- timestamp: boolean;
305
- colorize: boolean;
306
- metadata: Record<string, any>;
307
- transports?: TransportConfig[];
308
- }
309
- ```
57
+ Use named imports. There is no default export.
310
58
 
311
- `timestamp` and `colorize` apply to the **text** form only. The JSON envelope
312
- always carries a timestamp and is never colorized, so a structured log stream
313
- stays parseable. `colorize` additionally defers to the terminal: ANSI escapes are
314
- suppressed when stdout is not a TTY, and the `NO_COLOR` / `FORCE_COLOR`
315
- conventions are honored.
316
-
317
- ### Transports
318
-
319
- `transports` lists exactly where records go, in order. Omit it and you get the
320
- console alone.
321
-
322
- ```typescript
323
- import { LogLevel, NodeLogger } from 'logan-logger/node';
59
+ > **Upgrading from 1.x?** See the [migration guide](./docs/migration-2.0.md).
60
+ > Winston is gone, file logging is opt-in, and repeated object references are no
61
+ > longer reported as `[Circular]`.
324
62
 
325
- const logger = new NodeLogger({
326
- transports: [
327
- { type: 'console', options: { format: 'text', colorize: true } },
328
- { type: 'file', level: LogLevel.ERROR, options: { filename: 'logs/error.log' } }
329
- ]
330
- });
331
- ```
63
+ ## Runtimes
332
64
 
333
- | Type | Available from | Options |
65
+ | Runtime | Import | Notes |
334
66
  |---|---|---|
335
- | `console` | everywhere | `format`, `timestamp`, `colorize` |
336
- | `file` | `logan-logger/node`, `logan-logger/bun` | `filename`, `maxsize`, `maxFiles`, `format`, `timestamp` |
337
- | `custom` | everywhere | `transport` โ€” any object with a `write(entry)` method |
338
-
339
- Each transport is constructed behind its own guard: one failing to initialize
340
- warns and is dropped, and the rest keep working. The same applies at write time.
67
+ | Auto-detect | `logan-logger` | Also the right choice for Next.js and other isomorphic frameworks |
68
+ | Node.js 20+ | `logan-logger/node` | Adds the file transport and Morgan integration |
69
+ | Bun | `logan-logger/bun` | Same as Node |
70
+ | Browser / WebWorker | `logan-logger/browser` | CSS-styled console, performance marks, grouping |
71
+ | Deno | `jsr:@logan/logger` | Console; native implementation planned |
341
72
 
342
- A child logger **shares** its parent's transport instances, so
343
- `logger.child({ requestId })` per request costs no extra file handles.
73
+ Details and examples: [docs/runtimes.md](./docs/runtimes.md).
344
74
 
345
- Plug in your own destination either inline:
75
+ ## Configuring
346
76
 
347
- ```typescript
348
- const logger = new NodeLogger({
349
- transports: [{ type: 'custom', options: { transport: { type: 'syslog', write(entry) { /* โ€ฆ */ } } } }]
77
+ ```ts
78
+ createLogger({
79
+ level: LogLevel.INFO,
80
+ format: 'json', // or 'text'
81
+ timestamp: true, // text form only
82
+ colorize: false, // text form only, and only on a TTY
83
+ metadata: { service: 'api' }, // attached to every record
84
+ transports: [ // omit for console only
85
+ { type: 'console', options: {} },
86
+ { type: 'file', level: LogLevel.ERROR, options: { filename: 'logs/error.log' } },
87
+ ],
350
88
  });
351
89
  ```
352
90
 
353
- or by name, so it can be selected from configuration:
354
-
355
- ```typescript
356
- import { registerTransport } from 'logan-logger';
357
-
358
- registerTransport('syslog', (config, context) => new SyslogTransport(config.options));
359
- ```
360
-
361
- ## API Reference
362
-
363
- ### Core Methods
364
- ```typescript
365
- interface ILogger {
366
- debug(message: string | (() => string), metadata?: any): void;
367
- info(message: string | (() => string), metadata?: any): void;
368
- warn(message: string | (() => string), metadata?: any): void;
369
- error(message: string | (() => string), metadata?: any): void;
370
-
371
- setLevel(level: LogLevel): void;
372
- getLevel(): LogLevel;
373
- child(metadata: Record<string, any>): ILogger;
374
- }
375
- ```
376
-
377
- ### Factory Functions
378
- ```typescript
379
- // Create logger with explicit configuration
380
- createLogger(config?: Partial<LoggerConfig>): ILogger;
381
-
382
- // Create logger based on environment
383
- createLoggerForEnvironment(): ILogger;
384
- ```
385
-
386
- ## Development
91
+ `LOG_LEVEL`, `LOG_FORMAT`, `LOG_TIMESTAMP` and `LOG_COLOR` override this at
92
+ runtime, so an operator can turn up verbosity without a deploy. Libraries that
93
+ need to pin their own logging set `ignoreEnvironment: true`.
387
94
 
388
- ### Setup
389
- ```bash
390
- git clone <repository>
391
- cd logan-logger-ts
392
- pnpm install
393
- ```
95
+ Every field, every transport option, and the serialization rules:
96
+ [docs/configuration.md](./docs/configuration.md).
394
97
 
395
- ### Commands
396
- ```bash
397
- # Development
398
- pnpm dev # Run with bun
399
- pnpm test # Test watch mode
400
- pnpm test:run # Single test run
401
- pnpm test:ui # Test UI
402
-
403
- # Building
404
- pnpm build # Full build
405
- pnpm typecheck # Type checking
406
- pnpm lint # Code linting
407
-
408
- # Specific tests
409
- vitest run tests/logger.test.ts
410
- ```
98
+ ## Documentation
411
99
 
412
- ## Architecture
100
+ [**Full documentation index**](./docs/README.md)
413
101
 
414
- Logan Logger uses a **Factory + Adapter pattern**:
102
+ - [Configuration reference](./docs/configuration.md)
103
+ - [Runtimes and entry points](./docs/runtimes.md)
104
+ - [Environment variables](./docs/environment-variables.md)
105
+ - [Next.js](./docs/nextjs-compatibility.md) ยท [Bundlers](./docs/webpack-bundler-compatibility.md)
106
+ - [Troubleshooting](./docs/troubleshooting.md)
107
+ - [Migrating from 1.x](./docs/migration-2.0.md)
415
108
 
416
- 1. **Runtime Detection** - Automatically detects the current JavaScript environment
417
- 2. **Factory Creation** - Creates the appropriate logger implementation
418
- 3. **Runtime Adapters** - Optimized implementations for each environment
419
- 4. **Unified Interface** - Consistent API across all runtimes
420
-
421
- ### File Structure
422
- ```
423
- src/
424
- โ”œโ”€โ”€ core/ # Core interfaces and factory
425
- โ”œโ”€โ”€ runtime/ # Runtime-specific implementations
426
- โ”œโ”€โ”€ utils/ # Utilities (serialization, config, runtime detection)
427
- โ””โ”€โ”€ index.ts # Main exports
428
- ```
109
+ API documentation is generated from source on [JSR](https://jsr.io/@logan/logger/doc).
429
110
 
430
111
  ## Contributing
431
112
 
432
- 1. Fork the repository
433
- 2. Create a feature branch
434
- 3. Add tests for new functionality
435
- 4. Ensure all tests pass: `pnpm test:run`
436
- 5. Submit a pull request
113
+ See [CONTRIBUTING.md](./CONTRIBUTING.md) for setup, architecture and the release
114
+ process.
437
115
 
438
- ## License
439
-
440
- MIT License - see LICENSE file for details.
116
+ This library is the reference implementation of
117
+ [Treering](https://github.com/llbbl/treering), a language-neutral logging
118
+ specification with a conformance suite.
441
119
 
442
- ## Credits
120
+ ## License
443
121
 
444
- Created by Logan Lindquist Land
122
+ MIT ยฉ Logan Lindquist Land
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "logan-logger",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "packageManager": "pnpm@11.9.0",
5
5
  "description": "Universal TypeScript logging library for all JavaScript runtimes",
6
6
  "main": "dist/index.cjs",