@abdokouta/react-logger 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,886 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
+ var __decorateClass = (decorators, target, key, kind) => {
5
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
6
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
7
+ if (decorator = decorators[i])
8
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
9
+ if (kind && result) __defProp(target, key, result);
10
+ return result;
11
+ };
12
+ var __decorateParam = (index, decorator) => (target, key) => decorator(target, key, index);
13
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
14
+
15
+ // src/enums/log-level.enum.ts
16
+ var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
17
+ LogLevel2[LogLevel2["Debug"] = 0] = "Debug";
18
+ LogLevel2[LogLevel2["Info"] = 1] = "Info";
19
+ LogLevel2[LogLevel2["Warn"] = 2] = "Warn";
20
+ LogLevel2[LogLevel2["Error"] = 3] = "Error";
21
+ LogLevel2[LogLevel2["Fatal"] = 4] = "Fatal";
22
+ return LogLevel2;
23
+ })(LogLevel || {});
24
+
25
+ // src/services/logger.service.ts
26
+ import { Injectable, Inject } from "@abdokouta/react-di";
27
+
28
+ // src/logger.ts
29
+ var Logger = class {
30
+ constructor(config) {
31
+ __publicField(this, "config");
32
+ __publicField(this, "sharedContext", {});
33
+ this.config = config;
34
+ if (config.context) {
35
+ this.sharedContext = { ...config.context };
36
+ }
37
+ }
38
+ debug(message, context) {
39
+ this.log(LogLevel.DEBUG, message, context);
40
+ }
41
+ info(message, context) {
42
+ this.log(LogLevel.INFO, message, context);
43
+ }
44
+ warn(message, context) {
45
+ this.log(LogLevel.WARN, message, context);
46
+ }
47
+ error(message, context) {
48
+ this.log(LogLevel.ERROR, message, context);
49
+ }
50
+ fatal(message, context) {
51
+ this.log(LogLevel.FATAL, message, context);
52
+ }
53
+ withContext(context) {
54
+ this.sharedContext = { ...this.sharedContext, ...context };
55
+ return this;
56
+ }
57
+ withoutContext(keys) {
58
+ if (!keys) {
59
+ this.sharedContext = {};
60
+ } else {
61
+ for (const key of keys) {
62
+ delete this.sharedContext[key];
63
+ }
64
+ }
65
+ return this;
66
+ }
67
+ getTransporters() {
68
+ return this.config.transporters;
69
+ }
70
+ log(level, message, context) {
71
+ const entry = {
72
+ level,
73
+ message,
74
+ context: { ...this.sharedContext, ...context },
75
+ timestamp: /* @__PURE__ */ new Date()
76
+ };
77
+ for (const transporter of this.config.transporters) {
78
+ transporter.log(entry);
79
+ }
80
+ }
81
+ };
82
+
83
+ // src/constants/tokens.constant.ts
84
+ var LOGGER_CONFIG = /* @__PURE__ */ Symbol("LOGGER_CONFIG");
85
+
86
+ // src/services/logger.service.ts
87
+ var LoggerService = class {
88
+ /**
89
+ * Create a new logger service
90
+ *
91
+ * @param config - Logger configuration
92
+ */
93
+ constructor(config) {
94
+ /** Logger configuration */
95
+ __publicField(this, "config");
96
+ /** Cached channel instances */
97
+ __publicField(this, "channels", /* @__PURE__ */ new Map());
98
+ /** Default channel instance */
99
+ __publicField(this, "defaultChannel");
100
+ this.config = config;
101
+ }
102
+ /**
103
+ * Get a logger channel instance
104
+ *
105
+ * Returns the specified channel, or the default channel if no name is provided.
106
+ * Channels are lazily initialized and cached.
107
+ *
108
+ * @param name - Channel name (uses default if not specified)
109
+ * @returns Logger instance
110
+ * @throws Error if channel is not configured
111
+ *
112
+ * @example
113
+ * ```typescript
114
+ * // Use default channel
115
+ * const logger = loggerService.channel();
116
+ * logger.info('Default message');
117
+ *
118
+ * // Use specific channel
119
+ * const errorLogger = loggerService.channel('errors');
120
+ * errorLogger.error('Critical error');
121
+ * ```
122
+ */
123
+ channel(name) {
124
+ const channelName = name ?? this.config.default;
125
+ if (this.channels.has(channelName)) {
126
+ return this.channels.get(channelName);
127
+ }
128
+ const channel = this.resolve(channelName);
129
+ this.channels.set(channelName, channel);
130
+ return channel;
131
+ }
132
+ /**
133
+ * Log a message at the debug level (default channel)
134
+ *
135
+ * @param message - The log message
136
+ * @param context - Optional contextual data
137
+ *
138
+ * @example
139
+ * ```typescript
140
+ * loggerService.debug('Cache hit', { key: 'user:123' });
141
+ * ```
142
+ */
143
+ debug(message, context = {}) {
144
+ this.getDefaultChannel().debug(message, context);
145
+ }
146
+ /**
147
+ * Log a message at the info level (default channel)
148
+ *
149
+ * @param message - The log message
150
+ * @param context - Optional contextual data
151
+ *
152
+ * @example
153
+ * ```typescript
154
+ * loggerService.info('User logged in', { userId: '123' });
155
+ * ```
156
+ */
157
+ info(message, context = {}) {
158
+ this.getDefaultChannel().info(message, context);
159
+ }
160
+ /**
161
+ * Log a message at the warn level (default channel)
162
+ *
163
+ * @param message - The log message
164
+ * @param context - Optional contextual data
165
+ *
166
+ * @example
167
+ * ```typescript
168
+ * loggerService.warn('API rate limit approaching', { remaining: 10 });
169
+ * ```
170
+ */
171
+ warn(message, context = {}) {
172
+ this.getDefaultChannel().warn(message, context);
173
+ }
174
+ /**
175
+ * Log a message at the error level (default channel)
176
+ *
177
+ * @param message - The log message
178
+ * @param context - Optional contextual data
179
+ *
180
+ * @example
181
+ * ```typescript
182
+ * loggerService.error('Database connection failed', { error });
183
+ * ```
184
+ */
185
+ error(message, context = {}) {
186
+ this.getDefaultChannel().error(message, context);
187
+ }
188
+ /**
189
+ * Log a message at the fatal level (default channel)
190
+ *
191
+ * @param message - The log message
192
+ * @param context - Optional contextual data
193
+ *
194
+ * @example
195
+ * ```typescript
196
+ * loggerService.fatal('Application crashed', { error, stack });
197
+ * ```
198
+ */
199
+ fatal(message, context = {}) {
200
+ this.getDefaultChannel().fatal(message, context);
201
+ }
202
+ /**
203
+ * Add persistent context to the default channel
204
+ *
205
+ * @param context - Key-value pairs to add to the shared context
206
+ * @returns The logger service instance for fluent chaining
207
+ *
208
+ * @example
209
+ * ```typescript
210
+ * loggerService
211
+ * .withContext({ requestId: 'abc-123' })
212
+ * .withContext({ userId: 42 })
213
+ * .info('Processing request');
214
+ * ```
215
+ */
216
+ withContext(context) {
217
+ this.getDefaultChannel().withContext(context);
218
+ return this;
219
+ }
220
+ /**
221
+ * Remove keys from the default channel's shared context
222
+ *
223
+ * @param keys - Optional array of context keys to remove
224
+ * @returns The logger service instance for fluent chaining
225
+ *
226
+ * @example
227
+ * ```typescript
228
+ * // Remove specific keys
229
+ * loggerService.withoutContext(['userId', 'requestId']);
230
+ *
231
+ * // Clear all context
232
+ * loggerService.withoutContext();
233
+ * ```
234
+ */
235
+ withoutContext(keys) {
236
+ this.getDefaultChannel().withoutContext(keys);
237
+ return this;
238
+ }
239
+ /**
240
+ * Get all transporters from the default channel
241
+ *
242
+ * @returns Array of transporter instances
243
+ */
244
+ getTransporters() {
245
+ return this.getDefaultChannel().getTransporters();
246
+ }
247
+ /**
248
+ * Get the default channel name
249
+ *
250
+ * @returns Default channel name
251
+ */
252
+ getDefaultChannelName() {
253
+ return this.config.default;
254
+ }
255
+ /**
256
+ * Get all configured channel names
257
+ *
258
+ * @returns Array of channel names
259
+ */
260
+ getChannelNames() {
261
+ return Object.keys(this.config.channels);
262
+ }
263
+ /**
264
+ * Check if a channel is configured
265
+ *
266
+ * @param name - Channel name
267
+ * @returns True if the channel is configured
268
+ */
269
+ hasChannel(name) {
270
+ return name in this.config.channels;
271
+ }
272
+ /**
273
+ * Check if a channel is currently active (cached)
274
+ *
275
+ * @param name - Channel name (uses default if not specified)
276
+ * @returns True if the channel is active
277
+ */
278
+ isChannelActive(name) {
279
+ const channelName = name ?? this.config.default;
280
+ return this.channels.has(channelName);
281
+ }
282
+ /**
283
+ * Get the default channel instance
284
+ *
285
+ * @returns Logger instance
286
+ * @throws Error if default channel cannot be resolved
287
+ * @private
288
+ */
289
+ getDefaultChannel() {
290
+ if (this.defaultChannel) {
291
+ return this.defaultChannel;
292
+ }
293
+ const channelName = this.config.default;
294
+ if (this.channels.has(channelName)) {
295
+ this.defaultChannel = this.channels.get(channelName);
296
+ return this.defaultChannel;
297
+ }
298
+ this.defaultChannel = this.resolve(channelName);
299
+ this.channels.set(channelName, this.defaultChannel);
300
+ return this.defaultChannel;
301
+ }
302
+ /**
303
+ * Resolve a channel by name
304
+ *
305
+ * Creates a new logger instance based on channel configuration.
306
+ *
307
+ * @param name - Channel name
308
+ * @returns Logger instance
309
+ * @throws Error if channel is not configured
310
+ * @private
311
+ */
312
+ resolve(name) {
313
+ const channelConfig = this.config.channels[name];
314
+ if (!channelConfig) {
315
+ throw new Error(
316
+ `Logger channel [${name}] is not configured. Available channels: ${Object.keys(this.config.channels).join(", ")}`
317
+ );
318
+ }
319
+ return new Logger(channelConfig);
320
+ }
321
+ };
322
+ LoggerService = __decorateClass([
323
+ Injectable(),
324
+ __decorateParam(0, Inject(LOGGER_CONFIG))
325
+ ], LoggerService);
326
+
327
+ // src/logger.module.ts
328
+ import { Module, forRoot } from "@abdokouta/react-di";
329
+
330
+ // src/formatters/pretty.formatter.ts
331
+ var LEVEL_EMOJI = {
332
+ [0 /* Debug */]: "\u{1F41B}",
333
+ [1 /* Info */]: "\u2139\uFE0F",
334
+ [2 /* Warn */]: "\u26A0\uFE0F",
335
+ [3 /* Error */]: "\u274C",
336
+ [4 /* Fatal */]: "\u{1F480}"
337
+ };
338
+ var LEVEL_LABEL = {
339
+ [0 /* Debug */]: "DEBUG",
340
+ [1 /* Info */]: "INFO",
341
+ [2 /* Warn */]: "WARN",
342
+ [3 /* Error */]: "ERROR",
343
+ [4 /* Fatal */]: "FATAL"
344
+ };
345
+ var LEVEL_COLORS = {
346
+ [0 /* Debug */]: "color: #8B8B8B",
347
+ [1 /* Info */]: "color: #2196F3",
348
+ [2 /* Warn */]: "color: #FF9800",
349
+ [3 /* Error */]: "color: #F44336",
350
+ [4 /* Fatal */]: "color: #FFFFFF; background: #F44336; font-weight: bold; padding: 1px 4px; border-radius: 2px"
351
+ };
352
+ var PrettyFormatter = class {
353
+ /**
354
+ * Format a log entry into a pretty, human-readable string with
355
+ * emoji prefix, level badge, timestamp, message, and context.
356
+ *
357
+ * The returned string includes `%c` placeholders for CSS styling
358
+ * in the browser console. The ConsoleTransporter is responsible
359
+ * for passing the corresponding style strings.
360
+ *
361
+ * @param entry - The log entry to format.
362
+ * @returns The formatted string with CSS style placeholders.
363
+ */
364
+ format(entry) {
365
+ const emoji = LEVEL_EMOJI[entry.level];
366
+ const label = LEVEL_LABEL[entry.level];
367
+ const time = this.formatTimestamp(entry.timestamp);
368
+ const contextStr = this.formatContext(entry.context);
369
+ return `${emoji} %c[${label}]%c [${time}] ${entry.message}${contextStr}`;
370
+ }
371
+ /**
372
+ * Extract a short time string (HH:mm:ss.SSS) from an ISO timestamp.
373
+ *
374
+ * @param timestamp - ISO 8601 timestamp string.
375
+ * @returns A short time-only representation.
376
+ */
377
+ formatTimestamp(timestamp) {
378
+ try {
379
+ const date = new Date(timestamp);
380
+ const hours = String(date.getHours()).padStart(2, "0");
381
+ const minutes = String(date.getMinutes()).padStart(2, "0");
382
+ const seconds = String(date.getSeconds()).padStart(2, "0");
383
+ const ms = String(date.getMilliseconds()).padStart(3, "0");
384
+ return `${hours}:${minutes}:${seconds}.${ms}`;
385
+ } catch {
386
+ return timestamp;
387
+ }
388
+ }
389
+ /**
390
+ * Serialize context data into a compact, readable string.
391
+ * Returns an empty string when context is empty to keep output clean.
392
+ *
393
+ * @param context - The context record to serialize.
394
+ * @returns A formatted context string or empty string.
395
+ */
396
+ formatContext(context) {
397
+ const keys = Object.keys(context);
398
+ if (keys.length === 0) {
399
+ return "";
400
+ }
401
+ try {
402
+ return ` ${JSON.stringify(context)}`;
403
+ } catch {
404
+ return ` [context serialization failed]`;
405
+ }
406
+ }
407
+ };
408
+
409
+ // src/formatters/json.formatter.ts
410
+ var LEVEL_STRING = {
411
+ [0 /* Debug */]: "debug",
412
+ [1 /* Info */]: "info",
413
+ [2 /* Warn */]: "warn",
414
+ [3 /* Error */]: "error",
415
+ [4 /* Fatal */]: "fatal"
416
+ };
417
+ var JsonFormatter = class {
418
+ /**
419
+ * Format a log entry as a JSON string.
420
+ *
421
+ * Produces a flat JSON object with level (as string), message,
422
+ * timestamp, and context fields. Context is omitted when empty
423
+ * to keep output compact.
424
+ *
425
+ * @param entry - The log entry to format.
426
+ * @returns A JSON-serialized string representation of the entry.
427
+ */
428
+ format(entry) {
429
+ const payload = {
430
+ level: LEVEL_STRING[entry.level],
431
+ message: entry.message,
432
+ timestamp: entry.timestamp
433
+ };
434
+ if (Object.keys(entry.context).length > 0) {
435
+ payload.context = entry.context;
436
+ }
437
+ try {
438
+ return JSON.stringify(payload);
439
+ } catch {
440
+ return JSON.stringify({
441
+ level: LEVEL_STRING[entry.level],
442
+ message: entry.message,
443
+ timestamp: entry.timestamp,
444
+ error: "context serialization failed"
445
+ });
446
+ }
447
+ }
448
+ };
449
+
450
+ // src/formatters/simple.formatter.ts
451
+ var LEVEL_LABEL2 = {
452
+ [0 /* Debug */]: "DEBUG",
453
+ [1 /* Info */]: "INFO",
454
+ [2 /* Warn */]: "WARN",
455
+ [3 /* Error */]: "ERROR",
456
+ [4 /* Fatal */]: "FATAL"
457
+ };
458
+ var SimpleFormatter = class {
459
+ /**
460
+ * Format a log entry into a plain text line.
461
+ *
462
+ * Output pattern: `[LEVEL] [timestamp] message {context}`
463
+ *
464
+ * @param entry - The log entry to format.
465
+ * @returns A plain text string with no styling.
466
+ */
467
+ format(entry) {
468
+ const label = LEVEL_LABEL2[entry.level];
469
+ const contextStr = this.formatContext(entry.context);
470
+ return `[${label}] [${entry.timestamp}] ${entry.message}${contextStr}`;
471
+ }
472
+ /**
473
+ * Serialize context data into a compact string.
474
+ * Returns an empty string when context is empty.
475
+ *
476
+ * @param context - The context record to serialize.
477
+ * @returns A formatted context string or empty string.
478
+ */
479
+ formatContext(context) {
480
+ const keys = Object.keys(context);
481
+ if (keys.length === 0) {
482
+ return "";
483
+ }
484
+ try {
485
+ return ` ${JSON.stringify(context)}`;
486
+ } catch {
487
+ return " [context serialization failed]";
488
+ }
489
+ }
490
+ };
491
+
492
+ // src/transporters/silent.transporter.ts
493
+ var SilentTransporter = class {
494
+ /**
495
+ * Create a new SilentTransporter instance.
496
+ * All parameters are optional and exist only for interface compliance.
497
+ */
498
+ constructor() {
499
+ /**
500
+ The formatter instance (maintained for interface compliance). */
501
+ __publicField(this, "_formatter");
502
+ /**
503
+ The minimum log level (maintained for interface compliance). */
504
+ __publicField(this, "_level");
505
+ this._formatter = new SimpleFormatter();
506
+ this._level = 0 /* Debug */;
507
+ }
508
+ /**
509
+ * No-op transport method. Silently discards the entry.
510
+ *
511
+ * @param _entry - The log entry (ignored).
512
+ */
513
+ transport(_entry) {
514
+ }
515
+ /**
516
+ * Replace the current formatter.
517
+ *
518
+ * @param formatter - The new formatter instance.
519
+ */
520
+ setFormatter(formatter) {
521
+ this._formatter = formatter;
522
+ }
523
+ /**
524
+ * Retrieve the currently assigned formatter.
525
+ *
526
+ * @returns The active formatter instance.
527
+ */
528
+ getFormatter() {
529
+ return this._formatter;
530
+ }
531
+ /**
532
+ * Get the minimum log level.
533
+ *
534
+ * @returns The current minimum LogLevel threshold.
535
+ */
536
+ getLevel() {
537
+ return this._level;
538
+ }
539
+ /**
540
+ * Set the minimum log level.
541
+ *
542
+ * @param level - The new minimum LogLevel threshold.
543
+ */
544
+ setLevel(level) {
545
+ this._level = level;
546
+ }
547
+ };
548
+
549
+ // src/transporters/console.transporter.ts
550
+ var ConsoleTransporter = class {
551
+ /**
552
+ * Create a new ConsoleTransporter instance.
553
+ *
554
+ * @param options - Optional configuration for formatter and minimum level.
555
+ */
556
+ constructor(options = {}) {
557
+ /**
558
+ The formatter used to convert log entries into output strings. */
559
+ __publicField(this, "_formatter");
560
+ /**
561
+ The minimum log level threshold for this transporter. */
562
+ __publicField(this, "_level");
563
+ this._formatter = options.formatter ?? new PrettyFormatter();
564
+ this._level = options.level ?? 0 /* Debug */;
565
+ }
566
+ /**
567
+ * Deliver a log entry to the browser console.
568
+ *
569
+ * Routes the entry to the appropriate `console.*` method based on
570
+ * the log level. When using the PrettyFormatter, CSS styles are
571
+ * applied via `%c` placeholders for colored output.
572
+ *
573
+ * Entries below the configured minimum level are silently skipped.
574
+ *
575
+ * @param entry - The log entry to output.
576
+ */
577
+ transport(entry) {
578
+ if (entry.level < this._level) {
579
+ return;
580
+ }
581
+ const formatted = this._formatter.format(entry);
582
+ const method = this.resolveConsoleMethod(entry.level);
583
+ if (this._formatter instanceof PrettyFormatter) {
584
+ const levelStyle = LEVEL_COLORS[entry.level];
585
+ const resetStyle = "color: inherit";
586
+ method(formatted, levelStyle, resetStyle);
587
+ } else {
588
+ method(formatted);
589
+ }
590
+ }
591
+ /**
592
+ * Replace the current formatter.
593
+ *
594
+ * @param formatter - The new formatter instance to use.
595
+ */
596
+ setFormatter(formatter) {
597
+ this._formatter = formatter;
598
+ }
599
+ /**
600
+ * Retrieve the currently assigned formatter.
601
+ *
602
+ * @returns The active formatter instance.
603
+ */
604
+ getFormatter() {
605
+ return this._formatter;
606
+ }
607
+ /**
608
+ * Get the minimum log level this transporter handles.
609
+ *
610
+ * @returns The current minimum LogLevel threshold.
611
+ */
612
+ getLevel() {
613
+ return this._level;
614
+ }
615
+ /**
616
+ * Set the minimum log level this transporter handles.
617
+ *
618
+ * @param level - The new minimum LogLevel threshold.
619
+ */
620
+ setLevel(level) {
621
+ this._level = level;
622
+ }
623
+ /**
624
+ * Resolve the appropriate `console.*` method for a given log level.
625
+ *
626
+ * Maps logger severity levels to the closest browser console method
627
+ * to ensure proper DevTools filtering and visual distinction.
628
+ *
629
+ * @param level - The log level to resolve.
630
+ * @returns The bound console method function.
631
+ */
632
+ resolveConsoleMethod(level) {
633
+ switch (level) {
634
+ case 0 /* Debug */:
635
+ return console.debug.bind(console);
636
+ case 1 /* Info */:
637
+ return console.info.bind(console);
638
+ case 2 /* Warn */:
639
+ return console.warn.bind(console);
640
+ case 3 /* Error */:
641
+ return console.error.bind(console);
642
+ case 4 /* Fatal */:
643
+ return console.error.bind(console);
644
+ default:
645
+ return console.log.bind(console);
646
+ }
647
+ }
648
+ };
649
+
650
+ // src/logger.module.ts
651
+ var LoggerModule = class {
652
+ /**
653
+ * Configure the logger module
654
+ *
655
+ * @param config - Logger configuration (can be passed directly without defineConfig)
656
+ * @returns Dynamic module
657
+ *
658
+ * @example
659
+ * ```typescript
660
+ * LoggerModule.forRoot({
661
+ * default: 'console',
662
+ * channels: {
663
+ * console: {
664
+ * transporters: [new ConsoleTransporter()],
665
+ * },
666
+ * },
667
+ * })
668
+ * ```
669
+ */
670
+ static forRoot(config) {
671
+ const processedConfig = LoggerModule.processConfig(config);
672
+ return forRoot(LoggerModule, {
673
+ providers: [
674
+ {
675
+ provide: LOGGER_CONFIG,
676
+ useValue: processedConfig
677
+ },
678
+ LoggerService
679
+ ],
680
+ exports: [LoggerService, LOGGER_CONFIG]
681
+ });
682
+ }
683
+ /**
684
+ * Process configuration to add default transporters if needed
685
+ *
686
+ * @param config - Raw configuration
687
+ * @returns Processed configuration with defaults
688
+ * @private
689
+ */
690
+ static processConfig(config) {
691
+ const processedChannels = {};
692
+ for (const name in config.channels) {
693
+ if (Object.prototype.hasOwnProperty.call(config.channels, name)) {
694
+ const channelConfig = config.channels[name];
695
+ if (!channelConfig) continue;
696
+ if (!channelConfig.transporters || channelConfig.transporters.length === 0) {
697
+ if (name === "silent") {
698
+ processedChannels[name] = {
699
+ ...channelConfig,
700
+ transporters: [new SilentTransporter()]
701
+ };
702
+ } else {
703
+ processedChannels[name] = {
704
+ ...channelConfig,
705
+ transporters: [new ConsoleTransporter()]
706
+ };
707
+ }
708
+ } else {
709
+ processedChannels[name] = channelConfig;
710
+ }
711
+ }
712
+ }
713
+ return {
714
+ ...config,
715
+ channels: processedChannels
716
+ };
717
+ }
718
+ };
719
+ LoggerModule = __decorateClass([
720
+ Module({})
721
+ ], LoggerModule);
722
+
723
+ // src/config/logger.config.ts
724
+ function defineConfig(config) {
725
+ return config;
726
+ }
727
+
728
+ // src/transporters/storage.transporter.ts
729
+ var DEFAULT_STORAGE_KEY = "logger:entries";
730
+ var DEFAULT_MAX_ENTRIES = 100;
731
+ var StorageTransporter = class {
732
+ /**
733
+ * Create a new StorageTransporter instance.
734
+ *
735
+ * @param options - Optional configuration for storage key, limits, and formatter.
736
+ */
737
+ constructor(options = {}) {
738
+ /**
739
+ The formatter used to convert log entries into storable strings. */
740
+ __publicField(this, "_formatter");
741
+ /**
742
+ The minimum log level threshold for this transporter. */
743
+ __publicField(this, "_level");
744
+ /**
745
+ The localStorage key for persisting entries. */
746
+ __publicField(this, "_key");
747
+ /**
748
+ Maximum number of entries to retain. */
749
+ __publicField(this, "_maxEntries");
750
+ this._formatter = options.formatter ?? new JsonFormatter();
751
+ this._level = options.level ?? 0 /* Debug */;
752
+ this._key = options.key ?? DEFAULT_STORAGE_KEY;
753
+ this._maxEntries = options.maxEntries ?? DEFAULT_MAX_ENTRIES;
754
+ }
755
+ /**
756
+ * Persist a log entry to localStorage.
757
+ *
758
+ * The entry is formatted, appended to the existing entries array,
759
+ * and trimmed to the maximum entry limit. If localStorage is
760
+ * unavailable or full, the error is silently swallowed to avoid
761
+ * crashing the application.
762
+ *
763
+ * @param entry - The log entry to persist.
764
+ */
765
+ transport(entry) {
766
+ if (entry.level < this._level) {
767
+ return;
768
+ }
769
+ try {
770
+ const formatted = this._formatter.format(entry);
771
+ const entries = this.readEntries();
772
+ entries.push(formatted);
773
+ while (entries.length > this._maxEntries) {
774
+ entries.shift();
775
+ }
776
+ localStorage.setItem(this._key, JSON.stringify(entries));
777
+ } catch {
778
+ }
779
+ }
780
+ /**
781
+ * Replace the current formatter.
782
+ *
783
+ * @param formatter - The new formatter instance.
784
+ */
785
+ setFormatter(formatter) {
786
+ this._formatter = formatter;
787
+ }
788
+ /**
789
+ * Retrieve the currently assigned formatter.
790
+ *
791
+ * @returns The active formatter instance.
792
+ */
793
+ getFormatter() {
794
+ return this._formatter;
795
+ }
796
+ /**
797
+ * Get the minimum log level this transporter handles.
798
+ *
799
+ * @returns The current minimum LogLevel threshold.
800
+ */
801
+ getLevel() {
802
+ return this._level;
803
+ }
804
+ /**
805
+ * Set the minimum log level this transporter handles.
806
+ *
807
+ * @param level - The new minimum LogLevel threshold.
808
+ */
809
+ setLevel(level) {
810
+ this._level = level;
811
+ }
812
+ /**
813
+ * Clear all stored log entries from localStorage.
814
+ * Useful for manual cleanup or when resetting application state.
815
+ */
816
+ clear() {
817
+ try {
818
+ localStorage.removeItem(this._key);
819
+ } catch {
820
+ }
821
+ }
822
+ /**
823
+ * Retrieve all stored log entries from localStorage.
824
+ *
825
+ * @returns An array of formatted log entry strings.
826
+ */
827
+ getEntries() {
828
+ return this.readEntries();
829
+ }
830
+ /**
831
+ * Read the current entries array from localStorage.
832
+ * Returns an empty array if the key does not exist or parsing fails.
833
+ *
834
+ * @returns The parsed entries array.
835
+ */
836
+ readEntries() {
837
+ try {
838
+ const raw = localStorage.getItem(this._key);
839
+ if (!raw) {
840
+ return [];
841
+ }
842
+ const parsed = JSON.parse(raw);
843
+ return Array.isArray(parsed) ? parsed : [];
844
+ } catch {
845
+ return [];
846
+ }
847
+ }
848
+ };
849
+
850
+ // src/hooks/use-logger/use-logger.hook.ts
851
+ import { useInject } from "@abdokouta/react-di";
852
+ function useLogger(channelName) {
853
+ const loggerService = useInject(LoggerService);
854
+ if (channelName) {
855
+ return loggerService.channel(channelName);
856
+ }
857
+ return loggerService;
858
+ }
859
+
860
+ // src/hooks/use-logger-context/use-logger-context.hook.ts
861
+ import { useEffect } from "react";
862
+ function useLoggerContext(context, channelName) {
863
+ const logger = useLogger(channelName);
864
+ useEffect(() => {
865
+ logger.withContext(context);
866
+ return () => {
867
+ logger.withoutContext(Object.keys(context));
868
+ };
869
+ }, [logger, context]);
870
+ }
871
+ export {
872
+ ConsoleTransporter,
873
+ JsonFormatter,
874
+ LogLevel,
875
+ LoggerService as Logger,
876
+ LoggerModule,
877
+ LoggerService,
878
+ PrettyFormatter,
879
+ SilentTransporter,
880
+ SimpleFormatter,
881
+ StorageTransporter,
882
+ defineConfig,
883
+ useLogger,
884
+ useLoggerContext
885
+ };
886
+ //# sourceMappingURL=index.mjs.map