@vielzeug/logit 1.0.5 → 1.1.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.
package/README.md ADDED
@@ -0,0 +1,591 @@
1
+ # @vielzeug/logit
2
+
3
+ Powerful, type-safe console logging utility for TypeScript with styled output, log levels, scoped loggers, and remote logging support.
4
+
5
+ ## Features
6
+
7
+ - ✅ **Styled Console Output** - Beautiful colored logs with symbols, icons, or text
8
+ - ✅ **Log Level Filtering** - Control verbosity (debug, info, warn, error, off)
9
+ - ✅ **Scoped Loggers** - Create isolated loggers with namespaced prefixes
10
+ - ✅ **Remote Logging** - Send logs to external services (Sentry, Datadog, etc.)
11
+ - ✅ **Environment Detection** - Automatic production/development indicators
12
+ - ✅ **Timestamps** - Optional timestamp display
13
+ - ✅ **Type-Safe** - Full TypeScript support
14
+ - ✅ **Framework Agnostic** - Works in browser and Node.js
15
+ - ✅ **Zero Dependencies** - Lightweight with no external dependencies
16
+ - ✅ **Multiple Variants** - Symbol, icon, or text-based display modes
17
+
18
+ ## Installation
19
+
20
+ ::: code-group
21
+
22
+ ```sh [pnpm]
23
+ pnpm add @vielzeug/logit
24
+ ```
25
+
26
+ ```sh [npm]
27
+ npm install @vielzeug/logit
28
+ ```
29
+
30
+ ```sh [yarn]
31
+ yarn add @vielzeug/logit
32
+ ```
33
+
34
+ :::
35
+
36
+ ## Quick Start
37
+
38
+ ```typescript
39
+ import { Logit } from '@vielzeug/logit';
40
+
41
+ // Basic logging
42
+ Logit.info('Application started');
43
+ Logit.success('User authenticated');
44
+ Logit.warn('API rate limit approaching');
45
+ Logit.error('Failed to connect to database');
46
+
47
+ // With multiple arguments
48
+ Logit.debug('User data:', { id: 123, name: 'Alice' });
49
+
50
+ // Configure log level
51
+ Logit.setLogLevel('warn'); // Only warn and error messages will show
52
+
53
+ // Set namespace
54
+ Logit.setPrefix('MyApp');
55
+ Logit.info('This message has a namespace'); // [MYAPP] This message has a namespace
56
+ ```
57
+
58
+ ## Core Concepts
59
+
60
+ ### Log Levels
61
+
62
+ Control which logs are displayed based on severity:
63
+
64
+ ```typescript
65
+ // Set minimum log level
66
+ Logit.setLogLevel('warn');
67
+
68
+ Logit.debug('Not shown'); // ❌ Below threshold
69
+ Logit.info('Not shown'); // ❌ Below threshold
70
+ Logit.warn('Shown'); // ✅ At threshold
71
+ Logit.error('Shown'); // ✅ Above threshold
72
+
73
+ // Disable all logs
74
+ Logit.setLogLevel('off');
75
+
76
+ // Enable all logs
77
+ Logit.setLogLevel('debug');
78
+ ```
79
+
80
+ **Log Level Hierarchy (most to least verbose):**
81
+ ```
82
+ debug → trace → time → table → info → success → warn → error → off
83
+ ```
84
+
85
+ ### Display Variants
86
+
87
+ Choose how log messages are displayed:
88
+
89
+ ```typescript
90
+ // Symbol variant (default) - Unicode symbols
91
+ Logit.setVariant('symbol');
92
+ Logit.info('Message'); // 🅸 Message
93
+
94
+ // Icon variant - Icon characters
95
+ Logit.setVariant('icon');
96
+ Logit.info('Message'); // ℹ Message
97
+
98
+ // Text variant - Plain text labels
99
+ Logit.setVariant('text');
100
+ Logit.info('Message'); // INFO Message
101
+ ```
102
+
103
+ ### Namespaces
104
+
105
+ Add context to your logs with namespaces:
106
+
107
+ ```typescript
108
+ Logit.setPrefix('Auth');
109
+ Logit.info('Login attempt'); // [AUTH] Login attempt
110
+ Logit.error('Invalid credentials'); // [AUTH] Invalid credentials
111
+
112
+ // Clear namespace
113
+ Logit.setPrefix('');
114
+ ```
115
+
116
+ ### Scoped Loggers
117
+
118
+ Create isolated loggers without mutating global state:
119
+
120
+ ```typescript
121
+ // Global namespace
122
+ Logit.setPrefix('App');
123
+
124
+ // Create scoped loggers
125
+ const apiLogger = Logit.scope('api');
126
+ const dbLogger = Logit.scope('database');
127
+ const cacheLogger = Logit.scope('cache');
128
+
129
+ apiLogger.info('GET /users'); // [APP.API] GET /users
130
+ dbLogger.error('Connection timeout'); // [APP.DATABASE] Connection timeout
131
+ cacheLogger.debug('Cache hit'); // [APP.CACHE] Cache hit
132
+
133
+ // Global namespace unchanged
134
+ Logit.getPrefix(); // 'App'
135
+
136
+ // Nested scopes
137
+ Logit.setPrefix('App.api');
138
+ const v1Logger = Logit.scope('v1');
139
+ v1Logger.info('Request'); // [APP.API.V1] Request
140
+ ```
141
+
142
+ **Benefits:**
143
+ - No global state mutation
144
+ - Safe for concurrent operations
145
+ - Clean separation of concerns
146
+ - Easy to pass to modules/components
147
+
148
+ ## Advanced Features
149
+
150
+ ### Remote Logging
151
+
152
+ Send logs to external services for monitoring and error tracking:
153
+
154
+ ```typescript
155
+ // Configure remote handler
156
+ Logit.setRemote({
157
+ handler: (type, metadata) => {
158
+ // Send to your logging service
159
+ fetch('https://logs.example.com', {
160
+ method: 'POST',
161
+ body: JSON.stringify({
162
+ level: type,
163
+ message: metadata.args,
164
+ timestamp: metadata.timestamp,
165
+ namespace: metadata.namespace,
166
+ environment: metadata.environment,
167
+ }),
168
+ });
169
+ },
170
+ logLevel: 'warn', // Only send warn and error to remote
171
+ });
172
+
173
+ // Remote logging works independently
174
+ Logit.setLogLevel('debug'); // Console shows all logs
175
+ // But remote only receives warn/error
176
+
177
+ Logit.info('Local only'); // ✅ Console, ❌ Remote
178
+ Logit.warn('Both'); // ✅ Console, ✅ Remote
179
+ Logit.error('Both'); // ✅ Console, ✅ Remote
180
+ ```
181
+
182
+ **Metadata sent to handler:**
183
+ ```typescript
184
+ {
185
+ args: any[], // Log arguments
186
+ timestamp?: string, // ISO timestamp (if enabled)
187
+ namespace?: string, // Current namespace
188
+ environment: 'production' | 'development'
189
+ }
190
+ ```
191
+
192
+ **Integration examples:**
193
+
194
+ ```typescript
195
+ // Sentry
196
+ Logit.setRemote({
197
+ handler: (type, metadata) => {
198
+ if (type === 'error') {
199
+ Sentry.captureMessage(metadata.args.join(' '), {
200
+ level: 'error',
201
+ tags: { namespace: metadata.namespace },
202
+ });
203
+ }
204
+ },
205
+ logLevel: 'error',
206
+ });
207
+
208
+ // Datadog
209
+ Logit.setRemote({
210
+ handler: (type, metadata) => {
211
+ window.DD_LOGS?.logger.log(
212
+ type,
213
+ metadata.args.join(' '),
214
+ { namespace: metadata.namespace }
215
+ );
216
+ },
217
+ logLevel: 'info',
218
+ });
219
+
220
+ // Custom webhook
221
+ Logit.setRemote({
222
+ handler: async (type, metadata) => {
223
+ await fetch('/api/logs', {
224
+ method: 'POST',
225
+ headers: { 'Content-Type': 'application/json' },
226
+ body: JSON.stringify({ type, ...metadata }),
227
+ });
228
+ },
229
+ logLevel: 'warn',
230
+ });
231
+ ```
232
+
233
+ ### Environment Indicators
234
+
235
+ Automatically shows production/development indicators:
236
+
237
+ ```typescript
238
+ // Enable environment indicator (default)
239
+ Logit.showEnvironment(true);
240
+ Logit.info('Message'); // 🅸 🅳 Message (in development)
241
+ // 🅸 🅿 Message (in production)
242
+
243
+ // Disable environment indicator
244
+ Logit.showEnvironment(false);
245
+ Logit.info('Message'); // 🅸 Message
246
+ ```
247
+
248
+ ### Timestamps
249
+
250
+ Add timestamps to your logs:
251
+
252
+ ```typescript
253
+ // Enable timestamps (default)
254
+ Logit.showTimestamp(true);
255
+ Logit.info('Message'); // 🅸 🅳 14:23:45.123 Message
256
+
257
+ // Disable timestamps
258
+ Logit.showTimestamp(false);
259
+ Logit.info('Message'); // 🅸 🅳 Message
260
+ ```
261
+
262
+ ### Utility Methods
263
+
264
+ ```typescript
265
+ // Table display
266
+ const users = [
267
+ { id: 1, name: 'Alice', age: 30 },
268
+ { id: 2, name: 'Bob', age: 25 },
269
+ ];
270
+ Logit.table(users);
271
+ // Displays formatted table in console
272
+
273
+ // Timers
274
+ Logit.time('database-query');
275
+ await db.query('SELECT * FROM users');
276
+ Logit.timeEnd('database-query'); // database-query: 234ms
277
+
278
+ // Groups
279
+ Logit.groupCollapsed('API Request', 'GET', startTime);
280
+ Logit.info('URL:', '/api/users');
281
+ Logit.info('Status:', 200);
282
+ Logit.groupEnd();
283
+
284
+ // Assertions
285
+ Logit.assert(user !== null, 'User should exist', { userId: 123 });
286
+ ```
287
+
288
+ ## Configuration
289
+
290
+ ### Initialize with Options
291
+
292
+ ```typescript
293
+ Logit.setup({
294
+ logLevel: 'info', // Minimum log level
295
+ namespace: 'MyApp', // Global namespace
296
+ variant: 'symbol', // Display variant
297
+ timestamp: true, // Show timestamps
298
+ environment: true, // Show environment indicator
299
+ remote: { // Remote logging config
300
+ handler: remoteHandler,
301
+ logLevel: 'warn',
302
+ },
303
+ });
304
+ ```
305
+
306
+ ### Getters
307
+
308
+ ```typescript
309
+ Logit.getLevel(); // Current log level
310
+ Logit.getPrefix(); // Current namespace
311
+ Logit.getTimestamp(); // Timestamp enabled?
312
+ Logit.getEnvironment(); // Environment indicator enabled?
313
+ Logit.getVariant(); // Current variant
314
+ ```
315
+
316
+ ### Setters
317
+
318
+ ```typescript
319
+ Logit.setLogLevel('warn');
320
+ Logit.setPrefix('App');
321
+ Logit.toggleTimestamp(false);
322
+ Logit.toggleEnvironment(true);
323
+ Logit.setVariant('icon');
324
+ Logit.setRemote({ handler, logLevel: 'error' });
325
+ Logit.setRemoteLogLevel('warn');
326
+ ```
327
+
328
+ ## API Reference
329
+
330
+ ### Logging Methods
331
+
332
+ ```typescript
333
+ Logit.debug(...args: any[]): void
334
+ Logit.trace(...args: any[]): void
335
+ Logit.info(...args: any[]): void
336
+ Logit.success(...args: any[]): void
337
+ Logit.warn(...args: any[]): void
338
+ Logit.error(...args: any[]): void
339
+ ```
340
+
341
+ ### Scoped Logger
342
+
343
+ ```typescript
344
+ Logit.scope(namespace: string): ScopedLogger
345
+
346
+ // ScopedLogger has all logging methods:
347
+ {
348
+ debug: (...args: any[]) => void;
349
+ trace: (...args: any[]) => void;
350
+ info: (...args: any[]) => void;
351
+ success: (...args: any[]) => void;
352
+ warn: (...args: any[]) => void;
353
+ error: (...args: any[]) => void;
354
+ }
355
+ ```
356
+
357
+ ### Utility Methods
358
+
359
+ ```typescript
360
+ Logit.table(...args: any[]): void
361
+ Logit.time(label: string): void
362
+ Logit.timeEnd(label: string): void
363
+ Logit.groupCollapsed(text: string, label?: string, time?: number): void
364
+ Logit.groupEnd(): void
365
+ Logit.assert(valid: boolean, message: string, context: Record<string, any>): void
366
+ ```
367
+
368
+ ## Use Cases
369
+
370
+ ### Module-Specific Logging
371
+
372
+ ```typescript
373
+ // api.ts
374
+ const logger = Logit.scope('api');
375
+
376
+ export async function fetchUsers() {
377
+ logger.debug('Fetching users');
378
+ const response = await fetch('/api/users');
379
+ logger.info('Users fetched:', response.status);
380
+ return response.json();
381
+ }
382
+
383
+ // database.ts
384
+ const logger = Logit.scope('database');
385
+
386
+ export async function connect() {
387
+ logger.info('Connecting to database');
388
+ try {
389
+ await db.connect();
390
+ logger.success('Connected to database');
391
+ } catch (error) {
392
+ logger.error('Database connection failed:', error);
393
+ throw error;
394
+ }
395
+ }
396
+ ```
397
+
398
+ ### Debug vs Production
399
+
400
+ ```typescript
401
+ // During development
402
+ Logit.setLogLevel('debug');
403
+ Logit.showTimestamp(true);
404
+
405
+ // In production
406
+ if (process.env.NODE_ENV === 'production') {
407
+ Logit.setLogLevel('warn');
408
+ Logit.showTimestamp(false);
409
+ Logit.setRemote({
410
+ handler: sendToSentry,
411
+ logLevel: 'error',
412
+ });
413
+ }
414
+ ```
415
+
416
+ ### Error Tracking
417
+
418
+ ```typescript
419
+ Logit.setRemote({
420
+ handler: (type, metadata) => {
421
+ if (type === 'error') {
422
+ // Send to error tracking service
423
+ errorTracker.captureException({
424
+ message: metadata.args.join(' '),
425
+ timestamp: metadata.timestamp,
426
+ namespace: metadata.namespace,
427
+ environment: metadata.environment,
428
+ });
429
+ }
430
+ },
431
+ logLevel: 'error',
432
+ });
433
+
434
+ try {
435
+ await riskyOperation();
436
+ } catch (error) {
437
+ Logit.error('Operation failed:', error); // Logged locally + sent to tracker
438
+ }
439
+ ```
440
+
441
+ ### Performance Monitoring
442
+
443
+ ```typescript
444
+ Logit.time('page-load');
445
+
446
+ // Load application
447
+ await loadApp();
448
+
449
+ Logit.timeEnd('page-load'); // page-load: 1234ms
450
+
451
+ // With groups for detailed timing
452
+ Logit.groupCollapsed('Application Initialization');
453
+ Logit.time('load-config');
454
+ await loadConfig();
455
+ Logit.timeEnd('load-config');
456
+
457
+ Logit.time('init-modules');
458
+ await initModules();
459
+ Logit.timeEnd('init-modules');
460
+ Logit.groupEnd();
461
+ ```
462
+
463
+ ## Browser vs Node.js
464
+
465
+ ### Browser
466
+ - Styled console output with colors and symbols
467
+ - CSS-based formatting
468
+ - Environment detection via `import.meta.env` or `process.env`
469
+
470
+ ### Node.js
471
+ - Plain text output with labels
472
+ - No CSS styling
473
+ - Environment detection via `process.env.NODE_ENV`
474
+
475
+ **Example output:**
476
+
477
+ **Browser:**
478
+ ```
479
+ 🅸 🅳 14:23:45.123 User authenticated
480
+ ```
481
+
482
+ **Node.js:**
483
+ ```
484
+ INFO | 🅳 | User authenticated
485
+ ```
486
+
487
+ ## TypeScript Support
488
+
489
+ Full TypeScript support with exported types:
490
+
491
+ ```typescript
492
+ import {
493
+ Logit,
494
+ type LogitType,
495
+ type LogitLevel,
496
+ type LogitOptions,
497
+ type LogitRemoteOptions,
498
+ type ScopedLogger,
499
+ } from '@vielzeug/logit';
500
+
501
+ const options: LogitOptions = {
502
+ logLevel: 'info',
503
+ namespace: 'App',
504
+ variant: 'symbol',
505
+ };
506
+
507
+ Logit.setup(options);
508
+
509
+ const logger: ScopedLogger = Logit.scope('module');
510
+ ```
511
+
512
+ ## Best Practices
513
+
514
+ ### 1. Use Scoped Loggers for Modules
515
+
516
+ ```typescript
517
+ // ✅ Good - Each module has its own logger
518
+ const apiLogger = Logit.scope('api');
519
+ const dbLogger = Logit.scope('db');
520
+
521
+ // ❌ Avoid - Mutating global namespace
522
+ Logit.setPrefix('api');
523
+ Logit.info('Request');
524
+ Logit.setPrefix('db');
525
+ Logit.info('Query');
526
+ ```
527
+
528
+ ### 2. Set Appropriate Log Levels
529
+
530
+ ```typescript
531
+ // Development
532
+ Logit.setLogLevel('debug');
533
+
534
+ // Staging
535
+ Logit.setLogLevel('info');
536
+
537
+ // Production
538
+ Logit.setLogLevel('warn');
539
+ ```
540
+
541
+ ### 3. Use Remote Logging for Production Errors
542
+
543
+ ```typescript
544
+ if (process.env.NODE_ENV === 'production') {
545
+ Logit.setRemote({
546
+ handler: sendToErrorTracker,
547
+ logLevel: 'error',
548
+ });
549
+ }
550
+ ```
551
+
552
+ ### 4. Leverage Log Levels Appropriately
553
+
554
+ ```typescript
555
+ Logit.debug('Detailed debugging info'); // Development only
556
+ Logit.info('User logged in'); // General information
557
+ Logit.success('Payment processed'); // Success states
558
+ Logit.warn('API rate limit: 90%'); // Warnings
559
+ Logit.error('Payment failed:', error); // Errors
560
+ ```
561
+
562
+ ## Performance
563
+
564
+ - Minimal overhead when logs are filtered by level
565
+ - Lazy evaluation of timestamp and environment
566
+ - Async remote logging (Promise-based, non-blocking)
567
+ - Zero dependencies
568
+ - ~2.7KB gzipped
569
+
570
+ ## Browser Support
571
+
572
+ - Chrome/Edge 63+ (for styled console output)
573
+ - Firefox 58+
574
+ - Safari 13+
575
+ - Node.js 10+
576
+
577
+ ## License
578
+
579
+ MIT © [Helmuth Saatkamp](https://github.com/helmuthdu)
580
+
581
+ ## Links
582
+
583
+ - [GitHub Repository](https://github.com/helmuthdu/vielzeug)
584
+ - [Documentation](https://vielzeug.dev)
585
+ - [NPM Package](https://www.npmjs.com/package/@vielzeug/logit)
586
+ - [Issue Tracker](https://github.com/helmuthdu/vielzeug/issues)
587
+
588
+ ---
589
+
590
+ Part of the [Vielzeug](https://github.com/helmuthdu/vielzeug) ecosystem - A collection of type-safe utilities for modern web development.
591
+