@vielzeug/logit 1.0.5 → 1.1.1
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 +591 -0
- package/dist/index.d.ts +71 -11
- package/dist/logit.cjs +1 -1
- package/dist/logit.cjs.map +1 -1
- package/dist/logit.js +154 -71
- package/dist/logit.js.map +1 -1
- package/package.json +1 -1
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
|
+
- ~3KB 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 Duarte](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
|
+
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,10 @@ export declare const Logit: {
|
|
|
5
5
|
assert: (valid: boolean, message: string, context: Record<string, any>) => void;
|
|
6
6
|
debug: (...args: any[]) => void;
|
|
7
7
|
error: (...args: any[]) => void;
|
|
8
|
+
/**
|
|
9
|
+
* Gets whether the environment indicator is shown.
|
|
10
|
+
*/
|
|
11
|
+
getEnvironment: () => boolean;
|
|
8
12
|
/**
|
|
9
13
|
* Gets the current log level.
|
|
10
14
|
*/
|
|
@@ -17,6 +21,10 @@ export declare const Logit: {
|
|
|
17
21
|
* Gets whether timestamps are shown.
|
|
18
22
|
*/
|
|
19
23
|
getTimestamp: () => boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Gets the current display variant.
|
|
26
|
+
*/
|
|
27
|
+
getVariant: () => "text" | "symbol" | "icon";
|
|
20
28
|
/**
|
|
21
29
|
* Creates a collapsed group in the console.
|
|
22
30
|
*/
|
|
@@ -27,9 +35,22 @@ export declare const Logit: {
|
|
|
27
35
|
groupEnd: () => void;
|
|
28
36
|
info: (...args: any[]) => void;
|
|
29
37
|
/**
|
|
30
|
-
*
|
|
31
|
-
|
|
32
|
-
|
|
38
|
+
* Creates a scoped logger with a namespaced prefix.
|
|
39
|
+
* Does not mutate global state - returns an isolated logger instance.
|
|
40
|
+
*
|
|
41
|
+
* @param namespace - The namespace to prepend to all log messages
|
|
42
|
+
* @returns A scoped logger with all logging methods
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* const apiLogger = Logit.scope('api');
|
|
47
|
+
* apiLogger.info('Request received'); // [API] Request received
|
|
48
|
+
*
|
|
49
|
+
* const dbLogger = Logit.scope('database');
|
|
50
|
+
* dbLogger.error('Connection failed'); // [DATABASE] Connection failed
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
scope: (namespace: string) => ScopedLogger;
|
|
33
54
|
/**
|
|
34
55
|
* Sets the minimum log level to display.
|
|
35
56
|
*/
|
|
@@ -47,17 +68,16 @@ export declare const Logit: {
|
|
|
47
68
|
*/
|
|
48
69
|
setRemoteLogLevel: (level: LogitLevel) => void;
|
|
49
70
|
/**
|
|
50
|
-
*
|
|
71
|
+
* Configures Logit with custom options.
|
|
72
|
+
*
|
|
73
|
+
* Note: The remote option will be merged with existing remote config,
|
|
74
|
+
* not replaced entirely. To clear a remote handler, set remote.handler to undefined.
|
|
51
75
|
*/
|
|
52
|
-
|
|
76
|
+
setup: (options: LogitOptions) => void;
|
|
53
77
|
/**
|
|
54
|
-
*
|
|
55
|
-
*/
|
|
56
|
-
showEnvironment: (value: boolean) => void;
|
|
57
|
-
/**
|
|
58
|
-
* Shows or hides timestamps in logs.
|
|
78
|
+
* Sets the display variant (text, icon, or symbol).
|
|
59
79
|
*/
|
|
60
|
-
|
|
80
|
+
setVariant: (variant: "text" | "icon" | "symbol") => void;
|
|
61
81
|
success: (...args: any[]) => void;
|
|
62
82
|
/**
|
|
63
83
|
* Displays data in a table format.
|
|
@@ -71,6 +91,34 @@ export declare const Logit: {
|
|
|
71
91
|
* Ends a timer with the given label.
|
|
72
92
|
*/
|
|
73
93
|
timeEnd: (label: string) => void;
|
|
94
|
+
/**
|
|
95
|
+
* Toggles or sets the environment indicator visibility.
|
|
96
|
+
* When called without arguments, toggles the current state.
|
|
97
|
+
*
|
|
98
|
+
* @param value - Optional boolean to explicitly set the state
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```ts
|
|
102
|
+
* Logit.toggleEnvironment(); // Toggles current state
|
|
103
|
+
* Logit.toggleEnvironment(true); // Shows environment indicator
|
|
104
|
+
* Logit.toggleEnvironment(false); // Hides environment indicator
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
toggleEnvironment: (value?: boolean) => void;
|
|
108
|
+
/**
|
|
109
|
+
* Toggles or sets timestamp visibility in logs.
|
|
110
|
+
* When called without arguments, toggles the current state.
|
|
111
|
+
*
|
|
112
|
+
* @param value - Optional boolean to explicitly set the state
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```ts
|
|
116
|
+
* Logit.toggleTimestamp(); // Toggles current state
|
|
117
|
+
* Logit.toggleTimestamp(true); // Shows timestamps
|
|
118
|
+
* Logit.toggleTimestamp(false); // Hides timestamps
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
toggleTimestamp: (value?: boolean) => void;
|
|
74
122
|
trace: (...args: any[]) => void;
|
|
75
123
|
warn: (...args: any[]) => void;
|
|
76
124
|
};
|
|
@@ -107,4 +155,16 @@ export declare type LogitTheme = {
|
|
|
107
155
|
|
|
108
156
|
export declare type LogitType = 'debug' | 'trace' | 'time' | 'table' | 'info' | 'success' | 'warn' | 'error';
|
|
109
157
|
|
|
158
|
+
/**
|
|
159
|
+
* Scoped logger interface with namespaced logging methods.
|
|
160
|
+
*/
|
|
161
|
+
export declare type ScopedLogger = {
|
|
162
|
+
debug: (...args: any[]) => void;
|
|
163
|
+
error: (...args: any[]) => void;
|
|
164
|
+
info: (...args: any[]) => void;
|
|
165
|
+
success: (...args: any[]) => void;
|
|
166
|
+
trace: (...args: any[]) => void;
|
|
167
|
+
warn: (...args: any[]) => void;
|
|
168
|
+
};
|
|
169
|
+
|
|
110
170
|
export { }
|
package/dist/logit.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const h={},$="🄿",E="🄳",w={debug:"log",success:"log"},L=()=>typeof window<"u"&&h?.NODE_ENV?!1:typeof process<"u"&&process.env?.NODE_ENV?process.env.NODE_ENV==="production":!1,g=L(),_=typeof window<"u"&&window.matchMedia?.("(prefers-color-scheme: dark)").matches,u={debug:{bg:"#616161",border:"#424242",color:"#fff",icon:"☕",symbol:"🅳"},error:{bg:"#d32f2f",border:"#c62828",color:"#fff",icon:"✘",symbol:"🅴"},group:{bg:"#546e7a",border:"#455a64",color:"#fff",icon:"⚭",symbol:"🅶"},info:{bg:"#1976d2",border:"#1565c0",color:"#fff",icon:"ℹ",symbol:"🅸"},ns:_?{bg:"#fafafa",border:"#c7c7c7",color:"#000"}:{bg:"#424242",border:"#212121",color:"#fff"},success:{bg:"#689f38",border:"#558b2f",color:"#fff",icon:"✔",symbol:"🆂"},time:{bg:"#0097a7",border:"#00838f",color:"#fff",icon:"⏲",symbol:"🆃"},trace:{bg:"#d81b60",border:"#c2185b",color:"#fff",icon:"⛢",symbol:"🆃"},warn:{bg:"#ffb300",border:"#ffa000",color:"#fff",icon:"⚠",symbol:"🆆"}},m={debug:0,trace:1,time:2,table:3,info:4,success:5,warn:6,error:7,off:8},o={environment:!0,logLevel:"debug",namespace:"",remote:{handler:void 0,logLevel:"off"},timestamp:!0,variant:"symbol"},i=e=>m[o.logLevel]<=m[e],d=()=>new Date().toISOString().slice(11,23),p=()=>g?$:E,x=(e,n)=>{o.remote.handler&&m[o.remote.logLevel]<=m[e]&&Promise.resolve().then(()=>{o.remote.handler?.(e,{args:n,environment:g?"production":"development",namespace:o.namespace||void 0,timestamp:o.timestamp?d():void 0})})},f=e=>w[e]||e,y="border: 1px solid",D="border-radius: 4px",b="border-radius: 8px; font: italic small-caps bold 12px; font-weight: lighter; padding: 0 4px;",l=(e,n="")=>{const{bg:r,color:s,border:t}=u[e],c=`${y} ${t}; ${D}`;switch(o.variant){case"symbol":return`color: ${r}; ${c}; padding: 1px 1px 0${n}`;case"icon":return`color: ${r}; ${c}; padding: 0 3px${n}`;default:return`background: ${r}; color: ${s}; ${c}; font-weight: bold; padding: 0 3px${n}`}},v=e=>{const n=u[e],{variant:r}=o;return r==="text"||!n||!n[r]?e.toUpperCase():n[r]};function O(e){const{namespace:n,timestamp:r,environment:s}=o;let t=`%c${v(e)}%c`;const c=[l(e),""];return n&&(t+=` %c${n}%c`,c.push(l("ns",`; ${b}`),"")),s&&(t+=` %c${p()}%c`,c.push("color: darkgray","")),r&&(t+=` %c${d()}%c`,c.push("color: gray","")),{format:t,parts:c}}const a=(e,...n)=>{if(typeof window>"u"){const c=console[f(e)];c(`${v(e)} | ${p()} |`,...n);return}if(!i(e))return;const{format:r,parts:s}=O(e),t=console[f(e)];t(r,...s,...n),x(e,n)},S=e=>{const n=Math.floor(Date.now()-e);return n?`${n}ms`:""},N={assert:(e,n,r)=>console.assert(e,n,r),debug:(...e)=>a("debug",...e),error:(...e)=>a("error",...e),getEnvironment:()=>o.environment,getLevel:()=>o.logLevel,getPrefix:()=>o.namespace,getTimestamp:()=>o.timestamp,getVariant:()=>o.variant,groupCollapsed:(e,n="GROUP",r=Date.now())=>{if(!i("success"))return;const s=S(r),t=p(),c=o.timestamp?d():"";console.groupCollapsed(`%c${n}%c${o.namespace}%c${t}%c${c}%c${s}%c${e}`,l("group","; margin-right: 6px; padding: 1px 3px 0"),l("ns",`; ${b}; margin-right: 6px`),"color: darkgray; margin-right: 6px","color: gray; font-weight: lighter; margin-right: 6px","color: gray; font-weight: lighter; margin-right: 6px","color: inherit; font-weight: lighter")},groupEnd:()=>{i("success")&&console.groupEnd()},info:(...e)=>a("info",...e),scope:e=>{const n=o.namespace,r=n?`${n}.${e}`:e;return{debug:(...s)=>{const t=o.namespace;o.namespace=r,a("debug",...s),o.namespace=t},error:(...s)=>{const t=o.namespace;o.namespace=r,a("error",...s),o.namespace=t},info:(...s)=>{const t=o.namespace;o.namespace=r,a("info",...s),o.namespace=t},success:(...s)=>{const t=o.namespace;o.namespace=r,a("success",...s),o.namespace=t},trace:(...s)=>{const t=o.namespace;o.namespace=r,a("trace",...s),o.namespace=t},warn:(...s)=>{const t=o.namespace;o.namespace=r,a("warn",...s),o.namespace=t}}},setLogLevel:e=>{o.logLevel=e},setPrefix:e=>{o.namespace=e},setRemote:e=>{o.remote=e},setRemoteLogLevel:e=>{o.remote.logLevel=e},setup:e=>{e.remote&&(o.remote={...o.remote,...e.remote},delete e.remote),Object.assign(o,e)},setVariant:e=>{o.variant=e},success:(...e)=>a("success",...e),table:(...e)=>{i("table")&&console.table(...e)},time:e=>{i("time")&&console.time(e)},timeEnd:e=>{i("time")&&console.timeEnd(e)},toggleEnvironment:e=>{o.environment=e??!o.environment},toggleTimestamp:e=>{o.timestamp=e??!o.timestamp},trace:(...e)=>a("trace",...e),warn:(...e)=>a("warn",...e)};exports.Logit=N;
|
|
2
2
|
//# sourceMappingURL=logit.cjs.map
|
package/dist/logit.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logit.cjs","sources":["../src/logit.ts"],"sourcesContent":["/** biome-ignore-all lint/suspicious/noAssignInExpressions: - */\n/** biome-ignore-all lint/suspicious/noExplicitAny: - */\n\n/**\n * Environment indicator symbols.\n */\nconst ENV_PROD = '\\uD83C\\uDD3F'; // 🅿\nconst ENV_DEV = '\\uD83C\\uDD33'; // 🅳\n\n/**\n * Console method mappings for log types.\n */\nconst CONSOLE_METHOD_MAP: Record<string, keyof Console> = {\n debug: 'log',\n success: 'log',\n} as const;\n\n/**\n * Checks if the current environment is production.\n * Cached for performance - evaluated once at a module load.\n */\nconst isProduction = (): boolean => {\n // Browser environment (Vite, Webpack, etc.)\n if (typeof window !== 'undefined' && (import.meta as any)?.env?.NODE_ENV) {\n return (import.meta as any).env.NODE_ENV === 'production';\n }\n\n // Node.js environment\n // @ts-expect-error\n if (typeof process !== 'undefined' && (process as any).env?.NODE_ENV) {\n // @ts-expect-error\n return (process as any).env.NODE_ENV === 'production';\n }\n\n return false;\n};\n\n// Cache the result to avoid repeated checks\nconst IS_PROD = isProduction();\n\nexport type LogitInstance = typeof Logit;\nexport type LogitType = 'debug' | 'trace' | 'time' | 'table' | 'info' | 'success' | 'warn' | 'error';\nexport type LogitColors = Exclude<LogitType, 'table'> | 'group' | 'ns';\nexport type LogitLevel = LogitType | 'off';\nexport type LogitRemoteOptions = {\n handler?: (...args: any[]) => void;\n logLevel: LogitLevel;\n};\nexport type LogitOptions = {\n environment?: boolean;\n variant?: 'text' | 'symbol' | 'icon';\n logLevel?: LogitLevel;\n namespace?: string;\n remote?: LogitRemoteOptions;\n timestamp?: boolean;\n};\nexport type LogitTheme = { color: string; bg: string; border: string; icon?: string; symbol?: string };\n\n/**\n * Detects dark mode preference at module load time.\n * Note: This is intentionally static and won't update if the user changes their theme.\n */\nconst isDark = typeof window !== 'undefined' && window.matchMedia?.('(prefers-color-scheme: dark)').matches;\n\nconst Theme: Readonly<Record<LogitColors, LogitTheme>> = {\n debug: { bg: '#616161', border: '#424242', color: '#fff', icon: '\\u2615', symbol: '\\uD83C\\uDD73' },\n error: { bg: '#d32f2f', border: '#c62828', color: '#fff', icon: '\\u2718', symbol: '\\uD83C\\uDD74' },\n group: { bg: '#546e7a', border: '#455a64', color: '#fff', icon: '\\u26AD', symbol: '\\uD83C\\uDD76' },\n info: { bg: '#1976d2', border: '#1565c0', color: '#fff', icon: '\\u2139', symbol: '\\uD83C\\uDD78' },\n ns: isDark\n ? { bg: '#fafafa', border: '#c7c7c7', color: '#000' }\n : { bg: '#424242', border: '#212121', color: '#fff' },\n success: { bg: '#689f38', border: '#558b2f', color: '#fff', icon: '\\u2714', symbol: '\\uD83C\\uDD82' },\n time: { bg: '#0097a7', border: '#00838f', color: '#fff', icon: '\\u23F2', symbol: '\\uD83C\\uDD83' },\n trace: { bg: '#d81b60', border: '#c2185b', color: '#fff', icon: '\\u26e2', symbol: '\\uD83C\\uDD83' },\n warn: { bg: '#ffb300', border: '#ffa000', color: '#fff', icon: '\\u26a0', symbol: '\\uD83C\\uDD86' },\n};\n\n// biome-ignore assist/source/useSortedKeys: -\nconst logLevel: Readonly<Record<LogitLevel, number>> = {\n debug: 0,\n trace: 1,\n time: 2,\n table: 3,\n info: 4,\n success: 5,\n warn: 6,\n error: 7,\n off: 8,\n};\n\nconst state: Required<LogitOptions> = {\n environment: true,\n logLevel: 'debug',\n namespace: '',\n remote: { handler: undefined, logLevel: 'off' },\n timestamp: true,\n variant: 'symbol',\n};\n\n/**\n * Determines if a log message should be shown based on the current log level.\n */\nconst shouldLog = (type: LogitType): boolean => logLevel[state.logLevel] <= logLevel[type];\n\n/**\n * Gets the current timestamp in ISO format (HH:MM:SS.mmm).\n */\nconst getCurrentTimestamp = (): string => new Date().toISOString().slice(11, 23);\n\n/**\n * Gets the environment indicator symbol.\n */\nconst getEnvIndicator = (): string => (IS_PROD ? ENV_PROD : ENV_DEV);\n\n/**\n * Sends log data to remote handler if configured.\n */\nconst sendRemoteLog = (type: LogitType, args: any[]): void => {\n if (state.remote.handler && logLevel[state.remote.logLevel] <= logLevel[type]) {\n state.remote.handler(type, ...args);\n }\n};\n\n/**\n * Gets the console method for a given log type.\n */\nconst getConsoleMethod = (type: LogitType): keyof Console => {\n return (CONSOLE_METHOD_MAP[type] || type) as keyof Console;\n};\n\n/**\n * CSS style constants for consistent formatting.\n */\nconst BASE_BORDER_STYLE = 'border: 1px solid';\nconst BASE_BORDER_RADIUS = 'border-radius: 4px';\nconst NAMESPACE_STYLE = 'border-radius: 8px; font: italic small-caps bold 12px; font-weight: lighter';\n\n/**\n * Generates CSS styles for log messages based on theme and variant.\n */\nconst style = (type: LogitColors, extra = ''): string => {\n const { bg, color, border } = Theme[type];\n const baseStyle = `color: ${bg}; ${BASE_BORDER_STYLE} ${border}; ${BASE_BORDER_RADIUS}`;\n\n switch (state.variant) {\n case 'symbol':\n return `${baseStyle}; padding: 1px 1px 0${extra}`;\n case 'icon':\n return `${baseStyle}; padding: 0 3px${extra}`;\n default:\n return `background: ${bg}; color: ${color}; ${BASE_BORDER_STYLE} ${border}; ${BASE_BORDER_RADIUS}; font-weight: bold; padding: 0 3px${extra}`;\n }\n};\n\n/**\n * Gets the display value for a log type based on current variant.\n */\nconst getDisplayValue = (type: LogitType): string => {\n const theme = Theme[type as LogitColors];\n const { variant } = state;\n\n // For 'text' variant or if the variant key doesn't exist, use uppercase type\n if (variant === 'text' || !theme[variant]) {\n return type.toUpperCase();\n }\n\n return theme[variant] as string;\n};\n\n/**\n * Builds the format string and style parts for browser console logging.\n */\nfunction buildBrowserLogParts(type: LogitType): { format: string; parts: string[] } {\n const { namespace, timestamp, environment } = state;\n\n let format = `%c${getDisplayValue(type)}%c`;\n const parts: string[] = [style(type as LogitColors), ''];\n\n if (namespace) {\n format += ` %c${namespace}%c`;\n parts.push(style('ns', `; ${NAMESPACE_STYLE}`), '');\n }\n\n if (environment) {\n format += ` %c${getEnvIndicator()}%c`;\n parts.push('color: darkgray', '');\n }\n\n if (timestamp) {\n format += ` %c${getCurrentTimestamp()}%c`;\n parts.push('color: gray', '');\n }\n\n return { format, parts };\n}\n\n/**\n * Logs messages to the console with styling and metadata.\n */\nconst log = (type: LogitType, ...args: any[]): void => {\n // Server-side logging (Node.js)\n if (typeof window === 'undefined') {\n const consoleMethod = console[getConsoleMethod(type)] as (...a: any[]) => void;\n consoleMethod(`${getDisplayValue(type)} | ${getEnvIndicator()} |`, ...args);\n return;\n }\n\n // Check log level\n if (!shouldLog(type)) return;\n\n // Browser-side logging with styling\n const { format, parts } = buildBrowserLogParts(type);\n const consoleMethod = console[getConsoleMethod(type)] as (...a: any[]) => void;\n\n consoleMethod(format, ...parts, ...args);\n sendRemoteLog(type, args);\n};\n\n/**\n * Formats the elapsed time for display.\n */\nconst formatElapsedTime = (startTime: number): string => {\n const elapsed = Math.floor(Date.now() - startTime);\n return elapsed ? `${elapsed}ms` : '';\n};\n\nexport const Logit = {\n /**\n * Asserts a condition and logs an error if it's false.\n */\n assert: (valid: boolean, message: string, context: Record<string, any>): void =>\n console.assert(valid, message, context),\n\n debug: (...args: any[]): void => log('debug', ...args),\n error: (...args: any[]): void => log('error', ...args),\n\n /**\n * Gets the current log level.\n */\n getLevel: (): LogitLevel => state.logLevel,\n\n /**\n * Gets the current namespace prefix.\n */\n getPrefix: (): string => state.namespace,\n\n /**\n * Gets whether timestamps are shown.\n */\n getTimestamp: (): boolean => state.timestamp,\n\n /**\n * Creates a collapsed group in the console.\n */\n groupCollapsed: (text: string, label = 'GROUP', time = Date.now()): void => {\n if (!shouldLog('success')) return;\n\n const elapsed = formatElapsedTime(time);\n const env = getEnvIndicator();\n const timestamp = state.timestamp ? getCurrentTimestamp() : '';\n\n console.groupCollapsed(\n `%c${label}%c${state.namespace}%c${env}%c${timestamp}%c${elapsed}%c${text}`,\n style('group', '; margin-right: 6px; padding: 1px 3px 0'),\n style('ns', `; ${NAMESPACE_STYLE}; margin-right: 6px`),\n 'color: darkgray; margin-right: 6px',\n 'color: gray; font-weight: lighter; margin-right: 6px',\n 'color: gray; font-weight: lighter; margin-right: 6px',\n 'color: inherit; font-weight: lighter',\n );\n },\n\n /**\n * Ends the current console group.\n */\n groupEnd: (): void => {\n if (shouldLog('success')) console.groupEnd();\n },\n\n info: (...args: any[]): void => log('info', ...args),\n\n /**\n * Initializes Logit with custom options.\n */\n initialise: (options: LogitOptions): void => {\n Object.assign(state, options);\n },\n\n /**\n * Sets the minimum log level to display.\n */\n setLogLevel: (level: LogitLevel): void => {\n state.logLevel = level;\n },\n\n /**\n * Sets the namespace prefix for all logs.\n */\n setPrefix: (namespace: string): void => {\n state.namespace = namespace;\n },\n\n /**\n * Configures remote logging options.\n */\n setRemote: (remote: LogitRemoteOptions): void => {\n state.remote = remote;\n },\n\n /**\n * Sets the log level for remote logging.\n */\n setRemoteLogLevel: (level: LogitLevel): void => {\n state.remote.logLevel = level;\n },\n\n /**\n * Sets the display variant (text, icon, or symbol).\n */\n setVariant: (variant: 'text' | 'icon' | 'symbol'): void => {\n state.variant = variant;\n },\n\n /**\n * Shows or hides the environment indicator.\n */\n showEnvironment: (value: boolean): void => {\n state.environment = value;\n },\n\n /**\n * Shows or hides timestamps in logs.\n */\n showTimestamp: (value: boolean): void => {\n state.timestamp = value;\n },\n\n success: (...args: any[]): void => log('success', ...args),\n\n /**\n * Displays data in a table format.\n */\n table: (...args: any[]): void => {\n if (shouldLog('table')) console.table(...args);\n },\n\n /**\n * Starts a timer with the given label.\n */\n time: (label: string): void => {\n if (shouldLog('time')) console.time(label);\n },\n\n /**\n * Ends a timer with the given label.\n */\n timeEnd: (label: string): void => {\n if (shouldLog('time')) console.timeEnd(label);\n },\n\n trace: (...args: any[]): void => log('trace', ...args),\n warn: (...args: any[]): void => log('warn', ...args),\n};\n"],"names":["ENV_PROD","ENV_DEV","CONSOLE_METHOD_MAP","isProduction","__vite_import_meta_env__","IS_PROD","isDark","Theme","logLevel","state","shouldLog","type","getCurrentTimestamp","getEnvIndicator","sendRemoteLog","args","getConsoleMethod","BASE_BORDER_STYLE","BASE_BORDER_RADIUS","NAMESPACE_STYLE","style","extra","bg","color","border","baseStyle","getDisplayValue","theme","variant","buildBrowserLogParts","namespace","timestamp","environment","format","parts","log","consoleMethod","formatElapsedTime","startTime","elapsed","Logit","valid","message","context","text","label","time","env","options","level","remote","value"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"logit.cjs","sources":["../src/logit.ts"],"sourcesContent":["/** biome-ignore-all lint/suspicious/noAssignInExpressions: - */\n/** biome-ignore-all lint/suspicious/noExplicitAny: - */\n\n/**\n * Environment indicator symbols.\n */\nconst ENV_PROD = '\\uD83C\\uDD3F'; // 🅿\nconst ENV_DEV = '\\uD83C\\uDD33'; // 🅳\n\n/**\n * Console method mappings for log types.\n */\nconst CONSOLE_METHOD_MAP: Record<string, keyof Console> = {\n debug: 'log',\n success: 'log',\n} as const;\n\n/**\n * Checks if the current environment is production.\n * Cached for performance - evaluated once at a module load.\n *\n * Note: import.meta.env is available in Vite/Bundlers but may be undefined in some environments.\n * Using 'any' cast is necessary for cross-environment compatibility.\n */\nconst isProduction = (): boolean => {\n // Browser environment (Vite, Webpack, etc.)\n // import.meta.env may be undefined in some bundlers - safe check with optional chaining\n if (typeof window !== 'undefined' && (import.meta as any)?.env?.NODE_ENV) {\n return (import.meta as any).env.NODE_ENV === 'production';\n }\n\n // Node.js environment\n // @ts-expect-error - process.env exists in Node.js but not in browser\n if (typeof process !== 'undefined' && (process as any).env?.NODE_ENV) {\n // @ts-expect-error - process.env exists in Node.js\n return (process as any).env.NODE_ENV === 'production';\n }\n\n return false;\n};\n\n// Cache the result to avoid repeated checks\nconst IS_PROD = isProduction();\n\nexport type LogitInstance = typeof Logit;\nexport type LogitType = 'debug' | 'trace' | 'time' | 'table' | 'info' | 'success' | 'warn' | 'error';\nexport type LogitColors = Exclude<LogitType, 'table'> | 'group' | 'ns';\nexport type LogitLevel = LogitType | 'off';\nexport type LogitRemoteOptions = {\n handler?: (...args: any[]) => void;\n logLevel: LogitLevel;\n};\nexport type LogitOptions = {\n environment?: boolean;\n variant?: 'text' | 'symbol' | 'icon';\n logLevel?: LogitLevel;\n namespace?: string;\n remote?: LogitRemoteOptions;\n timestamp?: boolean;\n};\nexport type LogitTheme = { color: string; bg: string; border: string; icon?: string; symbol?: string };\n\n/**\n * Scoped logger interface with namespaced logging methods.\n */\nexport type ScopedLogger = {\n debug: (...args: any[]) => void;\n error: (...args: any[]) => void;\n info: (...args: any[]) => void;\n success: (...args: any[]) => void;\n trace: (...args: any[]) => void;\n warn: (...args: any[]) => void;\n};\n\n/**\n * Detects dark mode preference at module load time.\n * Note: This is intentionally static and won't update if the user changes their theme.\n */\nconst isDark = typeof window !== 'undefined' && window.matchMedia?.('(prefers-color-scheme: dark)').matches;\n\nconst Theme: Readonly<Record<LogitColors, LogitTheme>> = {\n debug: { bg: '#616161', border: '#424242', color: '#fff', icon: '\\u2615', symbol: '\\uD83C\\uDD73' },\n error: { bg: '#d32f2f', border: '#c62828', color: '#fff', icon: '\\u2718', symbol: '\\uD83C\\uDD74' },\n group: { bg: '#546e7a', border: '#455a64', color: '#fff', icon: '\\u26AD', symbol: '\\uD83C\\uDD76' },\n info: { bg: '#1976d2', border: '#1565c0', color: '#fff', icon: '\\u2139', symbol: '\\uD83C\\uDD78' },\n ns: isDark\n ? { bg: '#fafafa', border: '#c7c7c7', color: '#000' }\n : { bg: '#424242', border: '#212121', color: '#fff' },\n success: { bg: '#689f38', border: '#558b2f', color: '#fff', icon: '\\u2714', symbol: '\\uD83C\\uDD82' },\n time: { bg: '#0097a7', border: '#00838f', color: '#fff', icon: '\\u23F2', symbol: '\\uD83C\\uDD83' },\n trace: { bg: '#d81b60', border: '#c2185b', color: '#fff', icon: '\\u26e2', symbol: '\\uD83C\\uDD83' },\n warn: { bg: '#ffb300', border: '#ffa000', color: '#fff', icon: '\\u26a0', symbol: '\\uD83C\\uDD86' },\n};\n\n// biome-ignore assist/source/useSortedKeys: -\nconst logLevel: Readonly<Record<LogitLevel, number>> = {\n debug: 0,\n trace: 1,\n time: 2,\n table: 3,\n info: 4,\n success: 5,\n warn: 6,\n error: 7,\n off: 8,\n};\n\nconst state: Required<LogitOptions> = {\n environment: true,\n logLevel: 'debug',\n namespace: '',\n remote: { handler: undefined, logLevel: 'off' },\n timestamp: true,\n variant: 'symbol',\n};\n\n/**\n * Determines if a log message should be shown based on the current log level.\n */\nconst shouldLog = (type: LogitType): boolean => logLevel[state.logLevel] <= logLevel[type];\n\n/**\n * Gets the current timestamp in ISO format (HH:MM:SS.mmm).\n */\nconst getCurrentTimestamp = (): string => new Date().toISOString().slice(11, 23);\n\n/**\n * Gets the environment indicator symbol.\n */\nconst getEnvIndicator = (): string => (IS_PROD ? ENV_PROD : ENV_DEV);\n\n/**\n * Sends log data to a remote handler if configured.\n */\nconst sendRemoteLog = (type: LogitType, args: any[]): void => {\n if (state.remote.handler && logLevel[state.remote.logLevel] <= logLevel[type]) {\n Promise.resolve().then(() => {\n state.remote.handler?.(type, {\n args,\n environment: IS_PROD ? 'production' : 'development',\n namespace: state.namespace || undefined,\n timestamp: state.timestamp ? getCurrentTimestamp() : undefined,\n });\n });\n }\n};\n\n/**\n * Gets the console method for a given log type.\n */\nconst getConsoleMethod = (type: LogitType): keyof Console => {\n return (CONSOLE_METHOD_MAP[type] || type) as keyof Console;\n};\n\n/**\n * CSS style constants for consistent formatting.\n */\nconst BASE_BORDER_STYLE = 'border: 1px solid';\nconst BASE_BORDER_RADIUS = 'border-radius: 4px';\nconst NAMESPACE_STYLE = 'border-radius: 8px; font: italic small-caps bold 12px; font-weight: lighter; padding: 0 4px;';\n\n/**\n * Generates CSS styles for log messages based on theme and variant.\n *\n * @param type - Log type color scheme\n * @param extra - Additional CSS to append (should include leading semicolon if needed)\n */\nconst style = (type: LogitColors, extra = ''): string => {\n const { bg, color, border } = Theme[type];\n const baseStyle = `${BASE_BORDER_STYLE} ${border}; ${BASE_BORDER_RADIUS}`;\n\n switch (state.variant) {\n case 'symbol':\n // Symbol variant: colored text on a transparent background\n return `color: ${bg}; ${baseStyle}; padding: 1px 1px 0${extra}`;\n case 'icon':\n // Icon variant: colored text on a transparent background\n return `color: ${bg}; ${baseStyle}; padding: 0 3px${extra}`;\n default:\n // Text variant: white text on a colored background\n return `background: ${bg}; color: ${color}; ${baseStyle}; font-weight: bold; padding: 0 3px${extra}`;\n }\n};\n\n/**\n * Gets the display value for a log type based on the current variant.\n */\nconst getDisplayValue = (type: LogitType): string => {\n const theme = Theme[type as LogitColors];\n const { variant } = state;\n\n // For 'text' variant or if the variant property doesn't exist in theme, use uppercase type\n if (variant === 'text' || !theme || !theme[variant]) {\n return type.toUpperCase();\n }\n\n return theme[variant] as string;\n};\n\n/**\n * Builds the format string and style parts for browser console logging.\n */\nfunction buildBrowserLogParts(type: LogitType): { format: string; parts: string[] } {\n const { namespace, timestamp, environment } = state;\n\n let format = `%c${getDisplayValue(type)}%c`;\n const parts: string[] = [style(type as LogitColors), ''];\n\n if (namespace) {\n format += ` %c${namespace}%c`;\n parts.push(style('ns', `; ${NAMESPACE_STYLE}`), '');\n }\n\n if (environment) {\n format += ` %c${getEnvIndicator()}%c`;\n parts.push('color: darkgray', '');\n }\n\n if (timestamp) {\n format += ` %c${getCurrentTimestamp()}%c`;\n parts.push('color: gray', '');\n }\n\n return { format, parts };\n}\n\n/**\n * Logs messages to the console with styling and metadata.\n */\nconst log = (type: LogitType, ...args: any[]): void => {\n // Server-side logging (Node.js)\n if (typeof window === 'undefined') {\n const consoleMethod = console[getConsoleMethod(type)] as (...a: any[]) => void;\n consoleMethod(`${getDisplayValue(type)} | ${getEnvIndicator()} |`, ...args);\n return;\n }\n\n // Check the log level\n if (!shouldLog(type)) return;\n\n // Browser-side logging with styling\n const { format, parts } = buildBrowserLogParts(type);\n const consoleMethod = console[getConsoleMethod(type)] as (...a: any[]) => void;\n\n consoleMethod(format, ...parts, ...args);\n sendRemoteLog(type, args);\n};\n\n/**\n * Formats the elapsed time for display.\n */\nconst formatElapsedTime = (startTime: number): string => {\n const elapsed = Math.floor(Date.now() - startTime);\n return elapsed ? `${elapsed}ms` : '';\n};\n\nexport const Logit = {\n /**\n * Asserts a condition and logs an error if it's false.\n */\n assert: (valid: boolean, message: string, context: Record<string, any>): void =>\n console.assert(valid, message, context),\n\n debug: (...args: any[]): void => log('debug', ...args),\n error: (...args: any[]): void => log('error', ...args),\n\n /**\n * Gets whether the environment indicator is shown.\n */\n getEnvironment: (): boolean => state.environment,\n\n /**\n * Gets the current log level.\n */\n getLevel: (): LogitLevel => state.logLevel,\n\n /**\n * Gets the current namespace prefix.\n */\n getPrefix: (): string => state.namespace,\n\n /**\n * Gets whether timestamps are shown.\n */\n getTimestamp: (): boolean => state.timestamp,\n\n /**\n * Gets the current display variant.\n */\n getVariant: (): 'text' | 'symbol' | 'icon' => state.variant,\n\n /**\n * Creates a collapsed group in the console.\n */\n groupCollapsed: (text: string, label = 'GROUP', time = Date.now()): void => {\n if (!shouldLog('success')) return;\n\n const elapsed = formatElapsedTime(time);\n const env = getEnvIndicator();\n const timestamp = state.timestamp ? getCurrentTimestamp() : '';\n\n console.groupCollapsed(\n `%c${label}%c${state.namespace}%c${env}%c${timestamp}%c${elapsed}%c${text}`,\n style('group', '; margin-right: 6px; padding: 1px 3px 0'),\n style('ns', `; ${NAMESPACE_STYLE}; margin-right: 6px`),\n 'color: darkgray; margin-right: 6px',\n 'color: gray; font-weight: lighter; margin-right: 6px',\n 'color: gray; font-weight: lighter; margin-right: 6px',\n 'color: inherit; font-weight: lighter',\n );\n },\n\n /**\n * Ends the current console group.\n */\n groupEnd: (): void => {\n if (shouldLog('success')) console.groupEnd();\n },\n\n info: (...args: any[]): void => log('info', ...args),\n\n /**\n * Creates a scoped logger with a namespaced prefix.\n * Does not mutate global state - returns an isolated logger instance.\n *\n * @param namespace - The namespace to prepend to all log messages\n * @returns A scoped logger with all logging methods\n *\n * @example\n * ```ts\n * const apiLogger = Logit.scope('api');\n * apiLogger.info('Request received'); // [API] Request received\n *\n * const dbLogger = Logit.scope('database');\n * dbLogger.error('Connection failed'); // [DATABASE] Connection failed\n * ```\n */\n scope: (namespace: string): ScopedLogger => {\n const originalNamespace = state.namespace;\n const scopedNamespace = originalNamespace ? `${originalNamespace}.${namespace}` : namespace;\n\n return {\n debug: (...args: any[]) => {\n const prev = state.namespace;\n state.namespace = scopedNamespace;\n log('debug', ...args);\n state.namespace = prev;\n },\n error: (...args: any[]) => {\n const prev = state.namespace;\n state.namespace = scopedNamespace;\n log('error', ...args);\n state.namespace = prev;\n },\n info: (...args: any[]) => {\n const prev = state.namespace;\n state.namespace = scopedNamespace;\n log('info', ...args);\n state.namespace = prev;\n },\n success: (...args: any[]) => {\n const prev = state.namespace;\n state.namespace = scopedNamespace;\n log('success', ...args);\n state.namespace = prev;\n },\n trace: (...args: any[]) => {\n const prev = state.namespace;\n state.namespace = scopedNamespace;\n log('trace', ...args);\n state.namespace = prev;\n },\n warn: (...args: any[]) => {\n const prev = state.namespace;\n state.namespace = scopedNamespace;\n log('warn', ...args);\n state.namespace = prev;\n },\n };\n },\n\n /**\n * Sets the minimum log level to display.\n */\n setLogLevel: (level: LogitLevel): void => {\n state.logLevel = level;\n },\n\n /**\n * Sets the namespace prefix for all logs.\n */\n setPrefix: (namespace: string): void => {\n state.namespace = namespace;\n },\n\n /**\n * Configures remote logging options.\n */\n setRemote: (remote: LogitRemoteOptions): void => {\n state.remote = remote;\n },\n\n /**\n * Sets the log level for remote logging.\n */\n setRemoteLogLevel: (level: LogitLevel): void => {\n state.remote.logLevel = level;\n },\n\n /**\n * Configures Logit with custom options.\n *\n * Note: The remote option will be merged with existing remote config,\n * not replaced entirely. To clear a remote handler, set remote.handler to undefined.\n */\n setup: (options: LogitOptions): void => {\n if (options.remote) {\n state.remote = { ...state.remote, ...options.remote };\n delete (options as any).remote; // Remove to avoid Object.assign overwrite\n }\n Object.assign(state, options);\n },\n\n /**\n * Sets the display variant (text, icon, or symbol).\n */\n setVariant: (variant: 'text' | 'icon' | 'symbol'): void => {\n state.variant = variant;\n },\n\n success: (...args: any[]): void => log('success', ...args),\n\n /**\n * Displays data in a table format.\n */\n table: (...args: any[]): void => {\n if (shouldLog('table')) console.table(...args);\n },\n\n /**\n * Starts a timer with the given label.\n */\n time: (label: string): void => {\n if (shouldLog('time')) console.time(label);\n },\n\n /**\n * Ends a timer with the given label.\n */\n timeEnd: (label: string): void => {\n if (shouldLog('time')) console.timeEnd(label);\n },\n\n /**\n * Toggles or sets the environment indicator visibility.\n * When called without arguments, toggles the current state.\n *\n * @param value - Optional boolean to explicitly set the state\n *\n * @example\n * ```ts\n * Logit.toggleEnvironment(); // Toggles current state\n * Logit.toggleEnvironment(true); // Shows environment indicator\n * Logit.toggleEnvironment(false); // Hides environment indicator\n * ```\n */\n toggleEnvironment: (value?: boolean): void => {\n state.environment = value ?? !state.environment;\n },\n\n /**\n * Toggles or sets timestamp visibility in logs.\n * When called without arguments, toggles the current state.\n *\n * @param value - Optional boolean to explicitly set the state\n *\n * @example\n * ```ts\n * Logit.toggleTimestamp(); // Toggles current state\n * Logit.toggleTimestamp(true); // Shows timestamps\n * Logit.toggleTimestamp(false); // Hides timestamps\n * ```\n */\n toggleTimestamp: (value?: boolean): void => {\n state.timestamp = value ?? !state.timestamp;\n },\n\n trace: (...args: any[]): void => log('trace', ...args),\n warn: (...args: any[]): void => log('warn', ...args),\n};\n"],"names":["ENV_PROD","ENV_DEV","CONSOLE_METHOD_MAP","isProduction","__vite_import_meta_env__","IS_PROD","isDark","Theme","logLevel","state","shouldLog","type","getCurrentTimestamp","getEnvIndicator","sendRemoteLog","args","getConsoleMethod","BASE_BORDER_STYLE","BASE_BORDER_RADIUS","NAMESPACE_STYLE","style","extra","bg","color","border","baseStyle","getDisplayValue","theme","variant","buildBrowserLogParts","namespace","timestamp","environment","format","parts","log","consoleMethod","formatElapsedTime","startTime","elapsed","Logit","valid","message","context","text","label","time","env","originalNamespace","scopedNamespace","prev","level","remote","options","value"],"mappings":"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"}
|
package/dist/logit.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
const
|
|
2
|
-
const
|
|
1
|
+
const h = {};
|
|
2
|
+
const E = {
|
|
3
3
|
debug: "log",
|
|
4
4
|
success: "log"
|
|
5
|
-
},
|
|
5
|
+
}, $ = () => typeof window < "u" && h?.NODE_ENV ? !1 : typeof process < "u" && process.env?.NODE_ENV ? process.env.NODE_ENV === "production" : !1, g = $(), w = typeof window < "u" && window.matchMedia?.("(prefers-color-scheme: dark)").matches, u = {
|
|
6
6
|
debug: { bg: "#616161", border: "#424242", color: "#fff", icon: "☕", symbol: "🅳" },
|
|
7
7
|
error: { bg: "#d32f2f", border: "#c62828", color: "#fff", icon: "✘", symbol: "🅴" },
|
|
8
8
|
group: { bg: "#546e7a", border: "#455a64", color: "#fff", icon: "⚭", symbol: "🅶" },
|
|
9
9
|
info: { bg: "#1976d2", border: "#1565c0", color: "#fff", icon: "ℹ", symbol: "🅸" },
|
|
10
|
-
ns:
|
|
10
|
+
ns: w ? { bg: "#fafafa", border: "#c7c7c7", color: "#000" } : { bg: "#424242", border: "#212121", color: "#fff" },
|
|
11
11
|
success: { bg: "#689f38", border: "#558b2f", color: "#fff", icon: "✔", symbol: "🆂" },
|
|
12
12
|
time: { bg: "#0097a7", border: "#00838f", color: "#fff", icon: "⏲", symbol: "🆃" },
|
|
13
13
|
trace: { bg: "#d81b60", border: "#c2185b", color: "#fff", icon: "⛢", symbol: "🆃" },
|
|
14
14
|
warn: { bg: "#ffb300", border: "#ffa000", color: "#fff", icon: "⚠", symbol: "🆆" }
|
|
15
|
-
},
|
|
15
|
+
}, m = {
|
|
16
16
|
debug: 0,
|
|
17
17
|
trace: 1,
|
|
18
18
|
time: 2,
|
|
@@ -22,76 +22,91 @@ const v = {
|
|
|
22
22
|
warn: 6,
|
|
23
23
|
error: 7,
|
|
24
24
|
off: 8
|
|
25
|
-
},
|
|
25
|
+
}, o = {
|
|
26
26
|
environment: !0,
|
|
27
27
|
logLevel: "debug",
|
|
28
28
|
namespace: "",
|
|
29
29
|
remote: { handler: void 0, logLevel: "off" },
|
|
30
30
|
timestamp: !0,
|
|
31
31
|
variant: "symbol"
|
|
32
|
-
},
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
}, i = (e) => m[o.logLevel] <= m[e], p = () => (/* @__PURE__ */ new Date()).toISOString().slice(11, 23), d = () => g ? "🄿" : "🄳", _ = (e, n) => {
|
|
33
|
+
o.remote.handler && m[o.remote.logLevel] <= m[e] && Promise.resolve().then(() => {
|
|
34
|
+
o.remote.handler?.(e, {
|
|
35
|
+
args: n,
|
|
36
|
+
environment: g ? "production" : "development",
|
|
37
|
+
namespace: o.namespace || void 0,
|
|
38
|
+
timestamp: o.timestamp ? p() : void 0
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
}, f = (e) => E[e] || e, L = "border: 1px solid", x = "border-radius: 4px", b = "border-radius: 8px; font: italic small-caps bold 12px; font-weight: lighter; padding: 0 4px;", l = (e, n = "") => {
|
|
42
|
+
const { bg: r, color: s, border: t } = u[e], c = `${L} ${t}; ${x}`;
|
|
43
|
+
switch (o.variant) {
|
|
37
44
|
case "symbol":
|
|
38
|
-
return
|
|
45
|
+
return `color: ${r}; ${c}; padding: 1px 1px 0${n}`;
|
|
39
46
|
case "icon":
|
|
40
|
-
return
|
|
47
|
+
return `color: ${r}; ${c}; padding: 0 3px${n}`;
|
|
41
48
|
default:
|
|
42
|
-
return `background: ${
|
|
49
|
+
return `background: ${r}; color: ${s}; ${c}; font-weight: bold; padding: 0 3px${n}`;
|
|
43
50
|
}
|
|
44
|
-
},
|
|
45
|
-
const
|
|
46
|
-
return
|
|
51
|
+
}, v = (e) => {
|
|
52
|
+
const n = u[e], { variant: r } = o;
|
|
53
|
+
return r === "text" || !n || !n[r] ? e.toUpperCase() : n[r];
|
|
47
54
|
};
|
|
48
55
|
function D(e) {
|
|
49
|
-
const { namespace:
|
|
50
|
-
let
|
|
51
|
-
const
|
|
52
|
-
return
|
|
56
|
+
const { namespace: n, timestamp: r, environment: s } = o;
|
|
57
|
+
let t = `%c${v(e)}%c`;
|
|
58
|
+
const c = [l(e), ""];
|
|
59
|
+
return n && (t += ` %c${n}%c`, c.push(l("ns", `; ${b}`), "")), s && (t += ` %c${d()}%c`, c.push("color: darkgray", "")), r && (t += ` %c${p()}%c`, c.push("color: gray", "")), { format: t, parts: c };
|
|
53
60
|
}
|
|
54
|
-
const
|
|
61
|
+
const a = (e, ...n) => {
|
|
55
62
|
if (typeof window > "u") {
|
|
56
|
-
const
|
|
57
|
-
|
|
63
|
+
const c = console[f(e)];
|
|
64
|
+
c(`${v(e)} | ${d()} |`, ...n);
|
|
58
65
|
return;
|
|
59
66
|
}
|
|
60
|
-
if (!
|
|
61
|
-
const { format:
|
|
62
|
-
|
|
63
|
-
},
|
|
64
|
-
const
|
|
65
|
-
return
|
|
66
|
-
},
|
|
67
|
+
if (!i(e)) return;
|
|
68
|
+
const { format: r, parts: s } = D(e), t = console[f(e)];
|
|
69
|
+
t(r, ...s, ...n), _(e, n);
|
|
70
|
+
}, N = (e) => {
|
|
71
|
+
const n = Math.floor(Date.now() - e);
|
|
72
|
+
return n ? `${n}ms` : "";
|
|
73
|
+
}, O = {
|
|
67
74
|
/**
|
|
68
75
|
* Asserts a condition and logs an error if it's false.
|
|
69
76
|
*/
|
|
70
|
-
assert: (e,
|
|
71
|
-
debug: (...e) =>
|
|
72
|
-
error: (...e) =>
|
|
77
|
+
assert: (e, n, r) => console.assert(e, n, r),
|
|
78
|
+
debug: (...e) => a("debug", ...e),
|
|
79
|
+
error: (...e) => a("error", ...e),
|
|
80
|
+
/**
|
|
81
|
+
* Gets whether the environment indicator is shown.
|
|
82
|
+
*/
|
|
83
|
+
getEnvironment: () => o.environment,
|
|
73
84
|
/**
|
|
74
85
|
* Gets the current log level.
|
|
75
86
|
*/
|
|
76
|
-
getLevel: () =>
|
|
87
|
+
getLevel: () => o.logLevel,
|
|
77
88
|
/**
|
|
78
89
|
* Gets the current namespace prefix.
|
|
79
90
|
*/
|
|
80
|
-
getPrefix: () =>
|
|
91
|
+
getPrefix: () => o.namespace,
|
|
81
92
|
/**
|
|
82
93
|
* Gets whether timestamps are shown.
|
|
83
94
|
*/
|
|
84
|
-
getTimestamp: () =>
|
|
95
|
+
getTimestamp: () => o.timestamp,
|
|
96
|
+
/**
|
|
97
|
+
* Gets the current display variant.
|
|
98
|
+
*/
|
|
99
|
+
getVariant: () => o.variant,
|
|
85
100
|
/**
|
|
86
101
|
* Creates a collapsed group in the console.
|
|
87
102
|
*/
|
|
88
|
-
groupCollapsed: (e,
|
|
89
|
-
if (!
|
|
90
|
-
const
|
|
103
|
+
groupCollapsed: (e, n = "GROUP", r = Date.now()) => {
|
|
104
|
+
if (!i("success")) return;
|
|
105
|
+
const s = N(r), t = d(), c = o.timestamp ? p() : "";
|
|
91
106
|
console.groupCollapsed(
|
|
92
|
-
`%c${
|
|
93
|
-
|
|
94
|
-
|
|
107
|
+
`%c${n}%c${o.namespace}%c${t}%c${c}%c${s}%c${e}`,
|
|
108
|
+
l("group", "; margin-right: 6px; padding: 1px 3px 0"),
|
|
109
|
+
l("ns", `; ${b}; margin-right: 6px`),
|
|
95
110
|
"color: darkgray; margin-right: 6px",
|
|
96
111
|
"color: gray; font-weight: lighter; margin-right: 6px",
|
|
97
112
|
"color: gray; font-weight: lighter; margin-right: 6px",
|
|
@@ -102,80 +117,148 @@ const i = (e, ...o) => {
|
|
|
102
117
|
* Ends the current console group.
|
|
103
118
|
*/
|
|
104
119
|
groupEnd: () => {
|
|
105
|
-
|
|
120
|
+
i("success") && console.groupEnd();
|
|
106
121
|
},
|
|
107
|
-
info: (...e) =>
|
|
122
|
+
info: (...e) => a("info", ...e),
|
|
108
123
|
/**
|
|
109
|
-
*
|
|
124
|
+
* Creates a scoped logger with a namespaced prefix.
|
|
125
|
+
* Does not mutate global state - returns an isolated logger instance.
|
|
126
|
+
*
|
|
127
|
+
* @param namespace - The namespace to prepend to all log messages
|
|
128
|
+
* @returns A scoped logger with all logging methods
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```ts
|
|
132
|
+
* const apiLogger = Logit.scope('api');
|
|
133
|
+
* apiLogger.info('Request received'); // [API] Request received
|
|
134
|
+
*
|
|
135
|
+
* const dbLogger = Logit.scope('database');
|
|
136
|
+
* dbLogger.error('Connection failed'); // [DATABASE] Connection failed
|
|
137
|
+
* ```
|
|
110
138
|
*/
|
|
111
|
-
|
|
112
|
-
|
|
139
|
+
scope: (e) => {
|
|
140
|
+
const n = o.namespace, r = n ? `${n}.${e}` : e;
|
|
141
|
+
return {
|
|
142
|
+
debug: (...s) => {
|
|
143
|
+
const t = o.namespace;
|
|
144
|
+
o.namespace = r, a("debug", ...s), o.namespace = t;
|
|
145
|
+
},
|
|
146
|
+
error: (...s) => {
|
|
147
|
+
const t = o.namespace;
|
|
148
|
+
o.namespace = r, a("error", ...s), o.namespace = t;
|
|
149
|
+
},
|
|
150
|
+
info: (...s) => {
|
|
151
|
+
const t = o.namespace;
|
|
152
|
+
o.namespace = r, a("info", ...s), o.namespace = t;
|
|
153
|
+
},
|
|
154
|
+
success: (...s) => {
|
|
155
|
+
const t = o.namespace;
|
|
156
|
+
o.namespace = r, a("success", ...s), o.namespace = t;
|
|
157
|
+
},
|
|
158
|
+
trace: (...s) => {
|
|
159
|
+
const t = o.namespace;
|
|
160
|
+
o.namespace = r, a("trace", ...s), o.namespace = t;
|
|
161
|
+
},
|
|
162
|
+
warn: (...s) => {
|
|
163
|
+
const t = o.namespace;
|
|
164
|
+
o.namespace = r, a("warn", ...s), o.namespace = t;
|
|
165
|
+
}
|
|
166
|
+
};
|
|
113
167
|
},
|
|
114
168
|
/**
|
|
115
169
|
* Sets the minimum log level to display.
|
|
116
170
|
*/
|
|
117
171
|
setLogLevel: (e) => {
|
|
118
|
-
|
|
172
|
+
o.logLevel = e;
|
|
119
173
|
},
|
|
120
174
|
/**
|
|
121
175
|
* Sets the namespace prefix for all logs.
|
|
122
176
|
*/
|
|
123
177
|
setPrefix: (e) => {
|
|
124
|
-
|
|
178
|
+
o.namespace = e;
|
|
125
179
|
},
|
|
126
180
|
/**
|
|
127
181
|
* Configures remote logging options.
|
|
128
182
|
*/
|
|
129
183
|
setRemote: (e) => {
|
|
130
|
-
|
|
184
|
+
o.remote = e;
|
|
131
185
|
},
|
|
132
186
|
/**
|
|
133
187
|
* Sets the log level for remote logging.
|
|
134
188
|
*/
|
|
135
189
|
setRemoteLogLevel: (e) => {
|
|
136
|
-
|
|
137
|
-
},
|
|
138
|
-
/**
|
|
139
|
-
* Sets the display variant (text, icon, or symbol).
|
|
140
|
-
*/
|
|
141
|
-
setVariant: (e) => {
|
|
142
|
-
r.variant = e;
|
|
190
|
+
o.remote.logLevel = e;
|
|
143
191
|
},
|
|
144
192
|
/**
|
|
145
|
-
*
|
|
193
|
+
* Configures Logit with custom options.
|
|
194
|
+
*
|
|
195
|
+
* Note: The remote option will be merged with existing remote config,
|
|
196
|
+
* not replaced entirely. To clear a remote handler, set remote.handler to undefined.
|
|
146
197
|
*/
|
|
147
|
-
|
|
148
|
-
|
|
198
|
+
setup: (e) => {
|
|
199
|
+
e.remote && (o.remote = { ...o.remote, ...e.remote }, delete e.remote), Object.assign(o, e);
|
|
149
200
|
},
|
|
150
201
|
/**
|
|
151
|
-
*
|
|
202
|
+
* Sets the display variant (text, icon, or symbol).
|
|
152
203
|
*/
|
|
153
|
-
|
|
154
|
-
|
|
204
|
+
setVariant: (e) => {
|
|
205
|
+
o.variant = e;
|
|
155
206
|
},
|
|
156
|
-
success: (...e) =>
|
|
207
|
+
success: (...e) => a("success", ...e),
|
|
157
208
|
/**
|
|
158
209
|
* Displays data in a table format.
|
|
159
210
|
*/
|
|
160
211
|
table: (...e) => {
|
|
161
|
-
|
|
212
|
+
i("table") && console.table(...e);
|
|
162
213
|
},
|
|
163
214
|
/**
|
|
164
215
|
* Starts a timer with the given label.
|
|
165
216
|
*/
|
|
166
217
|
time: (e) => {
|
|
167
|
-
|
|
218
|
+
i("time") && console.time(e);
|
|
168
219
|
},
|
|
169
220
|
/**
|
|
170
221
|
* Ends a timer with the given label.
|
|
171
222
|
*/
|
|
172
223
|
timeEnd: (e) => {
|
|
173
|
-
|
|
224
|
+
i("time") && console.timeEnd(e);
|
|
225
|
+
},
|
|
226
|
+
/**
|
|
227
|
+
* Toggles or sets the environment indicator visibility.
|
|
228
|
+
* When called without arguments, toggles the current state.
|
|
229
|
+
*
|
|
230
|
+
* @param value - Optional boolean to explicitly set the state
|
|
231
|
+
*
|
|
232
|
+
* @example
|
|
233
|
+
* ```ts
|
|
234
|
+
* Logit.toggleEnvironment(); // Toggles current state
|
|
235
|
+
* Logit.toggleEnvironment(true); // Shows environment indicator
|
|
236
|
+
* Logit.toggleEnvironment(false); // Hides environment indicator
|
|
237
|
+
* ```
|
|
238
|
+
*/
|
|
239
|
+
toggleEnvironment: (e) => {
|
|
240
|
+
o.environment = e ?? !o.environment;
|
|
241
|
+
},
|
|
242
|
+
/**
|
|
243
|
+
* Toggles or sets timestamp visibility in logs.
|
|
244
|
+
* When called without arguments, toggles the current state.
|
|
245
|
+
*
|
|
246
|
+
* @param value - Optional boolean to explicitly set the state
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* ```ts
|
|
250
|
+
* Logit.toggleTimestamp(); // Toggles current state
|
|
251
|
+
* Logit.toggleTimestamp(true); // Shows timestamps
|
|
252
|
+
* Logit.toggleTimestamp(false); // Hides timestamps
|
|
253
|
+
* ```
|
|
254
|
+
*/
|
|
255
|
+
toggleTimestamp: (e) => {
|
|
256
|
+
o.timestamp = e ?? !o.timestamp;
|
|
174
257
|
},
|
|
175
|
-
trace: (...e) =>
|
|
176
|
-
warn: (...e) =>
|
|
258
|
+
trace: (...e) => a("trace", ...e),
|
|
259
|
+
warn: (...e) => a("warn", ...e)
|
|
177
260
|
};
|
|
178
261
|
export {
|
|
179
|
-
|
|
262
|
+
O as Logit
|
|
180
263
|
};
|
|
181
264
|
//# sourceMappingURL=logit.js.map
|
package/dist/logit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logit.js","sources":["../src/logit.ts"],"sourcesContent":["/** biome-ignore-all lint/suspicious/noAssignInExpressions: - */\n/** biome-ignore-all lint/suspicious/noExplicitAny: - */\n\n/**\n * Environment indicator symbols.\n */\nconst ENV_PROD = '\\uD83C\\uDD3F'; // 🅿\nconst ENV_DEV = '\\uD83C\\uDD33'; // 🅳\n\n/**\n * Console method mappings for log types.\n */\nconst CONSOLE_METHOD_MAP: Record<string, keyof Console> = {\n debug: 'log',\n success: 'log',\n} as const;\n\n/**\n * Checks if the current environment is production.\n * Cached for performance - evaluated once at a module load.\n */\nconst isProduction = (): boolean => {\n // Browser environment (Vite, Webpack, etc.)\n if (typeof window !== 'undefined' && (import.meta as any)?.env?.NODE_ENV) {\n return (import.meta as any).env.NODE_ENV === 'production';\n }\n\n // Node.js environment\n // @ts-expect-error\n if (typeof process !== 'undefined' && (process as any).env?.NODE_ENV) {\n // @ts-expect-error\n return (process as any).env.NODE_ENV === 'production';\n }\n\n return false;\n};\n\n// Cache the result to avoid repeated checks\nconst IS_PROD = isProduction();\n\nexport type LogitInstance = typeof Logit;\nexport type LogitType = 'debug' | 'trace' | 'time' | 'table' | 'info' | 'success' | 'warn' | 'error';\nexport type LogitColors = Exclude<LogitType, 'table'> | 'group' | 'ns';\nexport type LogitLevel = LogitType | 'off';\nexport type LogitRemoteOptions = {\n handler?: (...args: any[]) => void;\n logLevel: LogitLevel;\n};\nexport type LogitOptions = {\n environment?: boolean;\n variant?: 'text' | 'symbol' | 'icon';\n logLevel?: LogitLevel;\n namespace?: string;\n remote?: LogitRemoteOptions;\n timestamp?: boolean;\n};\nexport type LogitTheme = { color: string; bg: string; border: string; icon?: string; symbol?: string };\n\n/**\n * Detects dark mode preference at module load time.\n * Note: This is intentionally static and won't update if the user changes their theme.\n */\nconst isDark = typeof window !== 'undefined' && window.matchMedia?.('(prefers-color-scheme: dark)').matches;\n\nconst Theme: Readonly<Record<LogitColors, LogitTheme>> = {\n debug: { bg: '#616161', border: '#424242', color: '#fff', icon: '\\u2615', symbol: '\\uD83C\\uDD73' },\n error: { bg: '#d32f2f', border: '#c62828', color: '#fff', icon: '\\u2718', symbol: '\\uD83C\\uDD74' },\n group: { bg: '#546e7a', border: '#455a64', color: '#fff', icon: '\\u26AD', symbol: '\\uD83C\\uDD76' },\n info: { bg: '#1976d2', border: '#1565c0', color: '#fff', icon: '\\u2139', symbol: '\\uD83C\\uDD78' },\n ns: isDark\n ? { bg: '#fafafa', border: '#c7c7c7', color: '#000' }\n : { bg: '#424242', border: '#212121', color: '#fff' },\n success: { bg: '#689f38', border: '#558b2f', color: '#fff', icon: '\\u2714', symbol: '\\uD83C\\uDD82' },\n time: { bg: '#0097a7', border: '#00838f', color: '#fff', icon: '\\u23F2', symbol: '\\uD83C\\uDD83' },\n trace: { bg: '#d81b60', border: '#c2185b', color: '#fff', icon: '\\u26e2', symbol: '\\uD83C\\uDD83' },\n warn: { bg: '#ffb300', border: '#ffa000', color: '#fff', icon: '\\u26a0', symbol: '\\uD83C\\uDD86' },\n};\n\n// biome-ignore assist/source/useSortedKeys: -\nconst logLevel: Readonly<Record<LogitLevel, number>> = {\n debug: 0,\n trace: 1,\n time: 2,\n table: 3,\n info: 4,\n success: 5,\n warn: 6,\n error: 7,\n off: 8,\n};\n\nconst state: Required<LogitOptions> = {\n environment: true,\n logLevel: 'debug',\n namespace: '',\n remote: { handler: undefined, logLevel: 'off' },\n timestamp: true,\n variant: 'symbol',\n};\n\n/**\n * Determines if a log message should be shown based on the current log level.\n */\nconst shouldLog = (type: LogitType): boolean => logLevel[state.logLevel] <= logLevel[type];\n\n/**\n * Gets the current timestamp in ISO format (HH:MM:SS.mmm).\n */\nconst getCurrentTimestamp = (): string => new Date().toISOString().slice(11, 23);\n\n/**\n * Gets the environment indicator symbol.\n */\nconst getEnvIndicator = (): string => (IS_PROD ? ENV_PROD : ENV_DEV);\n\n/**\n * Sends log data to remote handler if configured.\n */\nconst sendRemoteLog = (type: LogitType, args: any[]): void => {\n if (state.remote.handler && logLevel[state.remote.logLevel] <= logLevel[type]) {\n state.remote.handler(type, ...args);\n }\n};\n\n/**\n * Gets the console method for a given log type.\n */\nconst getConsoleMethod = (type: LogitType): keyof Console => {\n return (CONSOLE_METHOD_MAP[type] || type) as keyof Console;\n};\n\n/**\n * CSS style constants for consistent formatting.\n */\nconst BASE_BORDER_STYLE = 'border: 1px solid';\nconst BASE_BORDER_RADIUS = 'border-radius: 4px';\nconst NAMESPACE_STYLE = 'border-radius: 8px; font: italic small-caps bold 12px; font-weight: lighter';\n\n/**\n * Generates CSS styles for log messages based on theme and variant.\n */\nconst style = (type: LogitColors, extra = ''): string => {\n const { bg, color, border } = Theme[type];\n const baseStyle = `color: ${bg}; ${BASE_BORDER_STYLE} ${border}; ${BASE_BORDER_RADIUS}`;\n\n switch (state.variant) {\n case 'symbol':\n return `${baseStyle}; padding: 1px 1px 0${extra}`;\n case 'icon':\n return `${baseStyle}; padding: 0 3px${extra}`;\n default:\n return `background: ${bg}; color: ${color}; ${BASE_BORDER_STYLE} ${border}; ${BASE_BORDER_RADIUS}; font-weight: bold; padding: 0 3px${extra}`;\n }\n};\n\n/**\n * Gets the display value for a log type based on current variant.\n */\nconst getDisplayValue = (type: LogitType): string => {\n const theme = Theme[type as LogitColors];\n const { variant } = state;\n\n // For 'text' variant or if the variant key doesn't exist, use uppercase type\n if (variant === 'text' || !theme[variant]) {\n return type.toUpperCase();\n }\n\n return theme[variant] as string;\n};\n\n/**\n * Builds the format string and style parts for browser console logging.\n */\nfunction buildBrowserLogParts(type: LogitType): { format: string; parts: string[] } {\n const { namespace, timestamp, environment } = state;\n\n let format = `%c${getDisplayValue(type)}%c`;\n const parts: string[] = [style(type as LogitColors), ''];\n\n if (namespace) {\n format += ` %c${namespace}%c`;\n parts.push(style('ns', `; ${NAMESPACE_STYLE}`), '');\n }\n\n if (environment) {\n format += ` %c${getEnvIndicator()}%c`;\n parts.push('color: darkgray', '');\n }\n\n if (timestamp) {\n format += ` %c${getCurrentTimestamp()}%c`;\n parts.push('color: gray', '');\n }\n\n return { format, parts };\n}\n\n/**\n * Logs messages to the console with styling and metadata.\n */\nconst log = (type: LogitType, ...args: any[]): void => {\n // Server-side logging (Node.js)\n if (typeof window === 'undefined') {\n const consoleMethod = console[getConsoleMethod(type)] as (...a: any[]) => void;\n consoleMethod(`${getDisplayValue(type)} | ${getEnvIndicator()} |`, ...args);\n return;\n }\n\n // Check log level\n if (!shouldLog(type)) return;\n\n // Browser-side logging with styling\n const { format, parts } = buildBrowserLogParts(type);\n const consoleMethod = console[getConsoleMethod(type)] as (...a: any[]) => void;\n\n consoleMethod(format, ...parts, ...args);\n sendRemoteLog(type, args);\n};\n\n/**\n * Formats the elapsed time for display.\n */\nconst formatElapsedTime = (startTime: number): string => {\n const elapsed = Math.floor(Date.now() - startTime);\n return elapsed ? `${elapsed}ms` : '';\n};\n\nexport const Logit = {\n /**\n * Asserts a condition and logs an error if it's false.\n */\n assert: (valid: boolean, message: string, context: Record<string, any>): void =>\n console.assert(valid, message, context),\n\n debug: (...args: any[]): void => log('debug', ...args),\n error: (...args: any[]): void => log('error', ...args),\n\n /**\n * Gets the current log level.\n */\n getLevel: (): LogitLevel => state.logLevel,\n\n /**\n * Gets the current namespace prefix.\n */\n getPrefix: (): string => state.namespace,\n\n /**\n * Gets whether timestamps are shown.\n */\n getTimestamp: (): boolean => state.timestamp,\n\n /**\n * Creates a collapsed group in the console.\n */\n groupCollapsed: (text: string, label = 'GROUP', time = Date.now()): void => {\n if (!shouldLog('success')) return;\n\n const elapsed = formatElapsedTime(time);\n const env = getEnvIndicator();\n const timestamp = state.timestamp ? getCurrentTimestamp() : '';\n\n console.groupCollapsed(\n `%c${label}%c${state.namespace}%c${env}%c${timestamp}%c${elapsed}%c${text}`,\n style('group', '; margin-right: 6px; padding: 1px 3px 0'),\n style('ns', `; ${NAMESPACE_STYLE}; margin-right: 6px`),\n 'color: darkgray; margin-right: 6px',\n 'color: gray; font-weight: lighter; margin-right: 6px',\n 'color: gray; font-weight: lighter; margin-right: 6px',\n 'color: inherit; font-weight: lighter',\n );\n },\n\n /**\n * Ends the current console group.\n */\n groupEnd: (): void => {\n if (shouldLog('success')) console.groupEnd();\n },\n\n info: (...args: any[]): void => log('info', ...args),\n\n /**\n * Initializes Logit with custom options.\n */\n initialise: (options: LogitOptions): void => {\n Object.assign(state, options);\n },\n\n /**\n * Sets the minimum log level to display.\n */\n setLogLevel: (level: LogitLevel): void => {\n state.logLevel = level;\n },\n\n /**\n * Sets the namespace prefix for all logs.\n */\n setPrefix: (namespace: string): void => {\n state.namespace = namespace;\n },\n\n /**\n * Configures remote logging options.\n */\n setRemote: (remote: LogitRemoteOptions): void => {\n state.remote = remote;\n },\n\n /**\n * Sets the log level for remote logging.\n */\n setRemoteLogLevel: (level: LogitLevel): void => {\n state.remote.logLevel = level;\n },\n\n /**\n * Sets the display variant (text, icon, or symbol).\n */\n setVariant: (variant: 'text' | 'icon' | 'symbol'): void => {\n state.variant = variant;\n },\n\n /**\n * Shows or hides the environment indicator.\n */\n showEnvironment: (value: boolean): void => {\n state.environment = value;\n },\n\n /**\n * Shows or hides timestamps in logs.\n */\n showTimestamp: (value: boolean): void => {\n state.timestamp = value;\n },\n\n success: (...args: any[]): void => log('success', ...args),\n\n /**\n * Displays data in a table format.\n */\n table: (...args: any[]): void => {\n if (shouldLog('table')) console.table(...args);\n },\n\n /**\n * Starts a timer with the given label.\n */\n time: (label: string): void => {\n if (shouldLog('time')) console.time(label);\n },\n\n /**\n * Ends a timer with the given label.\n */\n timeEnd: (label: string): void => {\n if (shouldLog('time')) console.timeEnd(label);\n },\n\n trace: (...args: any[]): void => log('trace', ...args),\n warn: (...args: any[]): void => log('warn', ...args),\n};\n"],"names":["CONSOLE_METHOD_MAP","isProduction","__vite_import_meta_env__","IS_PROD","isDark","Theme","logLevel","state","shouldLog","type","getCurrentTimestamp","getEnvIndicator","sendRemoteLog","args","getConsoleMethod","BASE_BORDER_STYLE","BASE_BORDER_RADIUS","NAMESPACE_STYLE","style","extra","bg","color","border","baseStyle","getDisplayValue","theme","variant","buildBrowserLogParts","namespace","timestamp","environment","format","parts","log","consoleMethod","formatElapsedTime","startTime","elapsed","Logit","valid","message","context","text","label","time","env","options","level","remote","value"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"logit.js","sources":["../src/logit.ts"],"sourcesContent":["/** biome-ignore-all lint/suspicious/noAssignInExpressions: - */\n/** biome-ignore-all lint/suspicious/noExplicitAny: - */\n\n/**\n * Environment indicator symbols.\n */\nconst ENV_PROD = '\\uD83C\\uDD3F'; // 🅿\nconst ENV_DEV = '\\uD83C\\uDD33'; // 🅳\n\n/**\n * Console method mappings for log types.\n */\nconst CONSOLE_METHOD_MAP: Record<string, keyof Console> = {\n debug: 'log',\n success: 'log',\n} as const;\n\n/**\n * Checks if the current environment is production.\n * Cached for performance - evaluated once at a module load.\n *\n * Note: import.meta.env is available in Vite/Bundlers but may be undefined in some environments.\n * Using 'any' cast is necessary for cross-environment compatibility.\n */\nconst isProduction = (): boolean => {\n // Browser environment (Vite, Webpack, etc.)\n // import.meta.env may be undefined in some bundlers - safe check with optional chaining\n if (typeof window !== 'undefined' && (import.meta as any)?.env?.NODE_ENV) {\n return (import.meta as any).env.NODE_ENV === 'production';\n }\n\n // Node.js environment\n // @ts-expect-error - process.env exists in Node.js but not in browser\n if (typeof process !== 'undefined' && (process as any).env?.NODE_ENV) {\n // @ts-expect-error - process.env exists in Node.js\n return (process as any).env.NODE_ENV === 'production';\n }\n\n return false;\n};\n\n// Cache the result to avoid repeated checks\nconst IS_PROD = isProduction();\n\nexport type LogitInstance = typeof Logit;\nexport type LogitType = 'debug' | 'trace' | 'time' | 'table' | 'info' | 'success' | 'warn' | 'error';\nexport type LogitColors = Exclude<LogitType, 'table'> | 'group' | 'ns';\nexport type LogitLevel = LogitType | 'off';\nexport type LogitRemoteOptions = {\n handler?: (...args: any[]) => void;\n logLevel: LogitLevel;\n};\nexport type LogitOptions = {\n environment?: boolean;\n variant?: 'text' | 'symbol' | 'icon';\n logLevel?: LogitLevel;\n namespace?: string;\n remote?: LogitRemoteOptions;\n timestamp?: boolean;\n};\nexport type LogitTheme = { color: string; bg: string; border: string; icon?: string; symbol?: string };\n\n/**\n * Scoped logger interface with namespaced logging methods.\n */\nexport type ScopedLogger = {\n debug: (...args: any[]) => void;\n error: (...args: any[]) => void;\n info: (...args: any[]) => void;\n success: (...args: any[]) => void;\n trace: (...args: any[]) => void;\n warn: (...args: any[]) => void;\n};\n\n/**\n * Detects dark mode preference at module load time.\n * Note: This is intentionally static and won't update if the user changes their theme.\n */\nconst isDark = typeof window !== 'undefined' && window.matchMedia?.('(prefers-color-scheme: dark)').matches;\n\nconst Theme: Readonly<Record<LogitColors, LogitTheme>> = {\n debug: { bg: '#616161', border: '#424242', color: '#fff', icon: '\\u2615', symbol: '\\uD83C\\uDD73' },\n error: { bg: '#d32f2f', border: '#c62828', color: '#fff', icon: '\\u2718', symbol: '\\uD83C\\uDD74' },\n group: { bg: '#546e7a', border: '#455a64', color: '#fff', icon: '\\u26AD', symbol: '\\uD83C\\uDD76' },\n info: { bg: '#1976d2', border: '#1565c0', color: '#fff', icon: '\\u2139', symbol: '\\uD83C\\uDD78' },\n ns: isDark\n ? { bg: '#fafafa', border: '#c7c7c7', color: '#000' }\n : { bg: '#424242', border: '#212121', color: '#fff' },\n success: { bg: '#689f38', border: '#558b2f', color: '#fff', icon: '\\u2714', symbol: '\\uD83C\\uDD82' },\n time: { bg: '#0097a7', border: '#00838f', color: '#fff', icon: '\\u23F2', symbol: '\\uD83C\\uDD83' },\n trace: { bg: '#d81b60', border: '#c2185b', color: '#fff', icon: '\\u26e2', symbol: '\\uD83C\\uDD83' },\n warn: { bg: '#ffb300', border: '#ffa000', color: '#fff', icon: '\\u26a0', symbol: '\\uD83C\\uDD86' },\n};\n\n// biome-ignore assist/source/useSortedKeys: -\nconst logLevel: Readonly<Record<LogitLevel, number>> = {\n debug: 0,\n trace: 1,\n time: 2,\n table: 3,\n info: 4,\n success: 5,\n warn: 6,\n error: 7,\n off: 8,\n};\n\nconst state: Required<LogitOptions> = {\n environment: true,\n logLevel: 'debug',\n namespace: '',\n remote: { handler: undefined, logLevel: 'off' },\n timestamp: true,\n variant: 'symbol',\n};\n\n/**\n * Determines if a log message should be shown based on the current log level.\n */\nconst shouldLog = (type: LogitType): boolean => logLevel[state.logLevel] <= logLevel[type];\n\n/**\n * Gets the current timestamp in ISO format (HH:MM:SS.mmm).\n */\nconst getCurrentTimestamp = (): string => new Date().toISOString().slice(11, 23);\n\n/**\n * Gets the environment indicator symbol.\n */\nconst getEnvIndicator = (): string => (IS_PROD ? ENV_PROD : ENV_DEV);\n\n/**\n * Sends log data to a remote handler if configured.\n */\nconst sendRemoteLog = (type: LogitType, args: any[]): void => {\n if (state.remote.handler && logLevel[state.remote.logLevel] <= logLevel[type]) {\n Promise.resolve().then(() => {\n state.remote.handler?.(type, {\n args,\n environment: IS_PROD ? 'production' : 'development',\n namespace: state.namespace || undefined,\n timestamp: state.timestamp ? getCurrentTimestamp() : undefined,\n });\n });\n }\n};\n\n/**\n * Gets the console method for a given log type.\n */\nconst getConsoleMethod = (type: LogitType): keyof Console => {\n return (CONSOLE_METHOD_MAP[type] || type) as keyof Console;\n};\n\n/**\n * CSS style constants for consistent formatting.\n */\nconst BASE_BORDER_STYLE = 'border: 1px solid';\nconst BASE_BORDER_RADIUS = 'border-radius: 4px';\nconst NAMESPACE_STYLE = 'border-radius: 8px; font: italic small-caps bold 12px; font-weight: lighter; padding: 0 4px;';\n\n/**\n * Generates CSS styles for log messages based on theme and variant.\n *\n * @param type - Log type color scheme\n * @param extra - Additional CSS to append (should include leading semicolon if needed)\n */\nconst style = (type: LogitColors, extra = ''): string => {\n const { bg, color, border } = Theme[type];\n const baseStyle = `${BASE_BORDER_STYLE} ${border}; ${BASE_BORDER_RADIUS}`;\n\n switch (state.variant) {\n case 'symbol':\n // Symbol variant: colored text on a transparent background\n return `color: ${bg}; ${baseStyle}; padding: 1px 1px 0${extra}`;\n case 'icon':\n // Icon variant: colored text on a transparent background\n return `color: ${bg}; ${baseStyle}; padding: 0 3px${extra}`;\n default:\n // Text variant: white text on a colored background\n return `background: ${bg}; color: ${color}; ${baseStyle}; font-weight: bold; padding: 0 3px${extra}`;\n }\n};\n\n/**\n * Gets the display value for a log type based on the current variant.\n */\nconst getDisplayValue = (type: LogitType): string => {\n const theme = Theme[type as LogitColors];\n const { variant } = state;\n\n // For 'text' variant or if the variant property doesn't exist in theme, use uppercase type\n if (variant === 'text' || !theme || !theme[variant]) {\n return type.toUpperCase();\n }\n\n return theme[variant] as string;\n};\n\n/**\n * Builds the format string and style parts for browser console logging.\n */\nfunction buildBrowserLogParts(type: LogitType): { format: string; parts: string[] } {\n const { namespace, timestamp, environment } = state;\n\n let format = `%c${getDisplayValue(type)}%c`;\n const parts: string[] = [style(type as LogitColors), ''];\n\n if (namespace) {\n format += ` %c${namespace}%c`;\n parts.push(style('ns', `; ${NAMESPACE_STYLE}`), '');\n }\n\n if (environment) {\n format += ` %c${getEnvIndicator()}%c`;\n parts.push('color: darkgray', '');\n }\n\n if (timestamp) {\n format += ` %c${getCurrentTimestamp()}%c`;\n parts.push('color: gray', '');\n }\n\n return { format, parts };\n}\n\n/**\n * Logs messages to the console with styling and metadata.\n */\nconst log = (type: LogitType, ...args: any[]): void => {\n // Server-side logging (Node.js)\n if (typeof window === 'undefined') {\n const consoleMethod = console[getConsoleMethod(type)] as (...a: any[]) => void;\n consoleMethod(`${getDisplayValue(type)} | ${getEnvIndicator()} |`, ...args);\n return;\n }\n\n // Check the log level\n if (!shouldLog(type)) return;\n\n // Browser-side logging with styling\n const { format, parts } = buildBrowserLogParts(type);\n const consoleMethod = console[getConsoleMethod(type)] as (...a: any[]) => void;\n\n consoleMethod(format, ...parts, ...args);\n sendRemoteLog(type, args);\n};\n\n/**\n * Formats the elapsed time for display.\n */\nconst formatElapsedTime = (startTime: number): string => {\n const elapsed = Math.floor(Date.now() - startTime);\n return elapsed ? `${elapsed}ms` : '';\n};\n\nexport const Logit = {\n /**\n * Asserts a condition and logs an error if it's false.\n */\n assert: (valid: boolean, message: string, context: Record<string, any>): void =>\n console.assert(valid, message, context),\n\n debug: (...args: any[]): void => log('debug', ...args),\n error: (...args: any[]): void => log('error', ...args),\n\n /**\n * Gets whether the environment indicator is shown.\n */\n getEnvironment: (): boolean => state.environment,\n\n /**\n * Gets the current log level.\n */\n getLevel: (): LogitLevel => state.logLevel,\n\n /**\n * Gets the current namespace prefix.\n */\n getPrefix: (): string => state.namespace,\n\n /**\n * Gets whether timestamps are shown.\n */\n getTimestamp: (): boolean => state.timestamp,\n\n /**\n * Gets the current display variant.\n */\n getVariant: (): 'text' | 'symbol' | 'icon' => state.variant,\n\n /**\n * Creates a collapsed group in the console.\n */\n groupCollapsed: (text: string, label = 'GROUP', time = Date.now()): void => {\n if (!shouldLog('success')) return;\n\n const elapsed = formatElapsedTime(time);\n const env = getEnvIndicator();\n const timestamp = state.timestamp ? getCurrentTimestamp() : '';\n\n console.groupCollapsed(\n `%c${label}%c${state.namespace}%c${env}%c${timestamp}%c${elapsed}%c${text}`,\n style('group', '; margin-right: 6px; padding: 1px 3px 0'),\n style('ns', `; ${NAMESPACE_STYLE}; margin-right: 6px`),\n 'color: darkgray; margin-right: 6px',\n 'color: gray; font-weight: lighter; margin-right: 6px',\n 'color: gray; font-weight: lighter; margin-right: 6px',\n 'color: inherit; font-weight: lighter',\n );\n },\n\n /**\n * Ends the current console group.\n */\n groupEnd: (): void => {\n if (shouldLog('success')) console.groupEnd();\n },\n\n info: (...args: any[]): void => log('info', ...args),\n\n /**\n * Creates a scoped logger with a namespaced prefix.\n * Does not mutate global state - returns an isolated logger instance.\n *\n * @param namespace - The namespace to prepend to all log messages\n * @returns A scoped logger with all logging methods\n *\n * @example\n * ```ts\n * const apiLogger = Logit.scope('api');\n * apiLogger.info('Request received'); // [API] Request received\n *\n * const dbLogger = Logit.scope('database');\n * dbLogger.error('Connection failed'); // [DATABASE] Connection failed\n * ```\n */\n scope: (namespace: string): ScopedLogger => {\n const originalNamespace = state.namespace;\n const scopedNamespace = originalNamespace ? `${originalNamespace}.${namespace}` : namespace;\n\n return {\n debug: (...args: any[]) => {\n const prev = state.namespace;\n state.namespace = scopedNamespace;\n log('debug', ...args);\n state.namespace = prev;\n },\n error: (...args: any[]) => {\n const prev = state.namespace;\n state.namespace = scopedNamespace;\n log('error', ...args);\n state.namespace = prev;\n },\n info: (...args: any[]) => {\n const prev = state.namespace;\n state.namespace = scopedNamespace;\n log('info', ...args);\n state.namespace = prev;\n },\n success: (...args: any[]) => {\n const prev = state.namespace;\n state.namespace = scopedNamespace;\n log('success', ...args);\n state.namespace = prev;\n },\n trace: (...args: any[]) => {\n const prev = state.namespace;\n state.namespace = scopedNamespace;\n log('trace', ...args);\n state.namespace = prev;\n },\n warn: (...args: any[]) => {\n const prev = state.namespace;\n state.namespace = scopedNamespace;\n log('warn', ...args);\n state.namespace = prev;\n },\n };\n },\n\n /**\n * Sets the minimum log level to display.\n */\n setLogLevel: (level: LogitLevel): void => {\n state.logLevel = level;\n },\n\n /**\n * Sets the namespace prefix for all logs.\n */\n setPrefix: (namespace: string): void => {\n state.namespace = namespace;\n },\n\n /**\n * Configures remote logging options.\n */\n setRemote: (remote: LogitRemoteOptions): void => {\n state.remote = remote;\n },\n\n /**\n * Sets the log level for remote logging.\n */\n setRemoteLogLevel: (level: LogitLevel): void => {\n state.remote.logLevel = level;\n },\n\n /**\n * Configures Logit with custom options.\n *\n * Note: The remote option will be merged with existing remote config,\n * not replaced entirely. To clear a remote handler, set remote.handler to undefined.\n */\n setup: (options: LogitOptions): void => {\n if (options.remote) {\n state.remote = { ...state.remote, ...options.remote };\n delete (options as any).remote; // Remove to avoid Object.assign overwrite\n }\n Object.assign(state, options);\n },\n\n /**\n * Sets the display variant (text, icon, or symbol).\n */\n setVariant: (variant: 'text' | 'icon' | 'symbol'): void => {\n state.variant = variant;\n },\n\n success: (...args: any[]): void => log('success', ...args),\n\n /**\n * Displays data in a table format.\n */\n table: (...args: any[]): void => {\n if (shouldLog('table')) console.table(...args);\n },\n\n /**\n * Starts a timer with the given label.\n */\n time: (label: string): void => {\n if (shouldLog('time')) console.time(label);\n },\n\n /**\n * Ends a timer with the given label.\n */\n timeEnd: (label: string): void => {\n if (shouldLog('time')) console.timeEnd(label);\n },\n\n /**\n * Toggles or sets the environment indicator visibility.\n * When called without arguments, toggles the current state.\n *\n * @param value - Optional boolean to explicitly set the state\n *\n * @example\n * ```ts\n * Logit.toggleEnvironment(); // Toggles current state\n * Logit.toggleEnvironment(true); // Shows environment indicator\n * Logit.toggleEnvironment(false); // Hides environment indicator\n * ```\n */\n toggleEnvironment: (value?: boolean): void => {\n state.environment = value ?? !state.environment;\n },\n\n /**\n * Toggles or sets timestamp visibility in logs.\n * When called without arguments, toggles the current state.\n *\n * @param value - Optional boolean to explicitly set the state\n *\n * @example\n * ```ts\n * Logit.toggleTimestamp(); // Toggles current state\n * Logit.toggleTimestamp(true); // Shows timestamps\n * Logit.toggleTimestamp(false); // Hides timestamps\n * ```\n */\n toggleTimestamp: (value?: boolean): void => {\n state.timestamp = value ?? !state.timestamp;\n },\n\n trace: (...args: any[]): void => log('trace', ...args),\n warn: (...args: any[]): void => log('warn', ...args),\n};\n"],"names":["CONSOLE_METHOD_MAP","isProduction","__vite_import_meta_env__","IS_PROD","isDark","Theme","logLevel","state","shouldLog","type","getCurrentTimestamp","getEnvIndicator","sendRemoteLog","args","getConsoleMethod","BASE_BORDER_STYLE","BASE_BORDER_RADIUS","NAMESPACE_STYLE","style","extra","bg","color","border","baseStyle","getDisplayValue","theme","variant","buildBrowserLogParts","namespace","timestamp","environment","format","parts","log","consoleMethod","formatElapsedTime","startTime","elapsed","Logit","valid","message","context","text","label","time","env","originalNamespace","scopedNamespace","prev","level","remote","options","value"],"mappings":"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"}
|