analogger 2.3.4 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -245,6 +245,19 @@ anaLogger.log({lid: 1236, symbol: "scissors"}, `I'am some log with some scissors
245
245
 
246
246
  <br/>
247
247
 
248
+ #### Example 6: The "only" filter
249
+
250
+ ###### You can filter logs globally so that only specific identifiers are displayed. This supports exact strings, partial matches, or regular expressions.
251
+
252
+ ```javascript
253
+ // Only show logs where the LID or context contains "API"
254
+ anaLogger.setOptions({ only: "API" });
255
+
256
+ anaLogger.log({ lid: "API_123" }, "This matches and will be seen");
257
+ anaLogger.log({ lid: "WEB_456" }, "This is blocked and hidden");
258
+ ```
259
+
260
+
248
261
  ---
249
262
 
250
263
  ### listSymbols()
@@ -312,6 +325,7 @@ Display the browser native message box if run from it; otherwise, it displays th
312
325
  | compressionLevel | 1 | number | _Gzip compression level (0-9)_ |
313
326
  | addArchiveTimestamp | true | boolean | _Appends a consistent timestamp to rotated files_ |
314
327
  | forceLidOn | false | boolean | _Automatically generates a short hash LID if one isn't provided_ |
328
+ | only | undefined | string/Regex/Array | Filter logs to show only those matching specific IDs or patterns |
315
329
 
316
330
  <br/>
317
331
 
package/ana-logger.d.cts CHANGED
@@ -75,6 +75,8 @@ declare class ____AnaLogger {
75
75
  NODE: string;
76
76
  OTHER: string;
77
77
  };
78
+ _localOnlyFilter: any;
79
+ _localOnlyLabel: string;
78
80
  getName(): string;
79
81
  getId(): string;
80
82
  /**
@@ -123,7 +125,7 @@ declare class ____AnaLogger {
123
125
  resetLogger(): void;
124
126
  remoteWaitCount: any;
125
127
  resetOptions(): void;
126
- setOptions({ timeLenMax, contextLenMax, idLenMax, lidLenMax, symbolLenMax, enableTrace, messageLenMax, hideLog, hideError, hideHookMessage, hidePassingTests, logToDom, logToFile, logMaxSize, logMaxArchives, logIndexArchive, addArchiveTimestamp, addArchiveIndex, compressArchives, compressionLevel, logToRemote, logToRemoteUrl, logToRemoteBinaryUrl, loopback, requiredLogLevel, oneConsolePerContext, silent, enableDate, enableMillisec, logToLocalStorage, logToLocalStorageMax, logToLocalStorageSize, logToRemoteMaxEntries, logToRemoteDebounce, logToRemoteMaxSize, logToRemoteMinSize, logUidToRemote, protocol, host, port, pathname, binarypathname, loadHtmlToImage }?: any): void;
128
+ setOptions({ timeLenMax, contextLenMax, idLenMax, lidLenMax, only, symbolLenMax, enableTrace, messageLenMax, hideLog, hideError, hideHookMessage, hidePassingTests, logToDom, logToFile, logMaxSize, logMaxArchives, logIndexArchive, addArchiveTimestamp, addArchiveIndex, compressArchives, compressionLevel, logToRemote, logToRemoteUrl, logToRemoteBinaryUrl, loopback, requiredLogLevel, oneConsolePerContext, silent, enableDate, enableMillisec, logToLocalStorage, logToLocalStorageMax, logToLocalStorageSize, logToRemoteMaxEntries, logToRemoteDebounce, logToRemoteMaxSize, logToRemoteMinSize, logUidToRemote, protocol, host, port, pathname, binarypathname, loadHtmlToImage }?: any): void;
127
129
  EOL: string;
128
130
  updateOptions(options: any): void;
129
131
  getOptions(): {
@@ -721,6 +721,12 @@ class ____AnaLogger
721
721
  this.#initialiseDefault();
722
722
 
723
723
  this.resetLogHistory();
724
+
725
+ // Tracks the active local "only" filter across calls.
726
+ // _localOnlyFilter holds the raw value (for matching),
727
+ // _localOnlyLabel holds the stringified form (for change-detection and separator text).
728
+ this._localOnlyFilter = undefined;
729
+ this._localOnlyLabel = undefined;
724
730
  }
725
731
 
726
732
  getName()
@@ -932,6 +938,7 @@ class ____AnaLogger
932
938
  this.options.contextLenMax = 10;
933
939
  this.options.idLenMax = 5;
934
940
  this.options.lidLenMax = 6;
941
+ this.options.only = undefined;
935
942
  this.options.messageLenMax = undefined;
936
943
  this.options.symbolLenMax = 60;
937
944
  this.options.hideHookMessage = undefined;
@@ -981,6 +988,7 @@ class ____AnaLogger
981
988
  contextLenMax = 10,
982
989
  idLenMax = 5,
983
990
  lidLenMax = 6,
991
+ only = undefined,
984
992
  symbolLenMax = 2,
985
993
  enableTrace = true,
986
994
  messageLenMax = undefined,
@@ -1026,6 +1034,7 @@ class ____AnaLogger
1026
1034
  this.options.contextLenMax = contextLenMax;
1027
1035
  this.options.idLenMax = idLenMax;
1028
1036
  this.options.lidLenMax = lidLenMax;
1037
+ this.options.only = only;
1029
1038
  this.options.messageLenMax = messageLenMax;
1030
1039
  this.options.symbolLenMax = symbolLenMax;
1031
1040
 
@@ -2582,6 +2591,114 @@ class ____AnaLogger
2582
2591
  return result;
2583
2592
  }
2584
2593
 
2594
+ /**
2595
+ * Handle the local "only" option on a log context.
2596
+ *
2597
+ * Rules:
2598
+ * - If context.only is not set, do nothing.
2599
+ * - If context.only does NOT match context.lid (using the same partial-string /
2600
+ * regex logic as the global filter), the call is suppressed (returns false).
2601
+ * - On the very first matching call, the output channel is cleared:
2602
+ * • Browser → console.clear()
2603
+ * • Node → writes the terminal-reset sequence (\x1bc) to stdout
2604
+ * - On a subsequent matching call whose only value differs from the last seen
2605
+ * value, a separator line is printed instead of clearing.
2606
+ *
2607
+ * Returns false when the log entry should be suppressed, true otherwise.
2608
+ *
2609
+ * @param {object} context
2610
+ * @returns {boolean}
2611
+ */
2612
+ #handleLocalOnly(context)
2613
+ {
2614
+ const localOnly = context.only;
2615
+
2616
+ // Helper: test a lid string against a single filter entry.
2617
+ const lidMatchesFilter = (filter, lid) =>
2618
+ {
2619
+ if (filter instanceof RegExp)
2620
+ {
2621
+ return filter.test(lid);
2622
+ }
2623
+ if (typeof filter === "string" || filter instanceof String)
2624
+ {
2625
+ return lid.includes(filter);
2626
+ }
2627
+ return filter === lid;
2628
+ };
2629
+
2630
+ // Helper: test a lid against a filter that may be a single value or an array.
2631
+ const lidMatchesAny = (filter, lid) => Array.isArray(filter)
2632
+ ? filter.some((f) => lidMatchesFilter(f, lid))
2633
+ : lidMatchesFilter(filter, lid);
2634
+
2635
+ // Stable string label for a filter value (used for change-detection and separator text).
2636
+ const toLabel = (filter) => Array.isArray(filter)
2637
+ ? filter.map((f) => (f instanceof RegExp ? f.toString() : String(f))).join(", ")
2638
+ : (filter instanceof RegExp ? filter.toString() : String(filter));
2639
+
2640
+ const lid = context.lid || "";
2641
+
2642
+ if (localOnly === undefined || localOnly === null)
2643
+ {
2644
+ // No local only on this call. If a filter is already active, enforce it.
2645
+ if (this._localOnlyFilter !== undefined)
2646
+ {
2647
+ return lidMatchesAny(this._localOnlyFilter, lid);
2648
+ }
2649
+
2650
+ // No active filter at all – let the call through.
2651
+ return true;
2652
+ }
2653
+
2654
+ // --- This call explicitly sets context.only ---
2655
+
2656
+ if (!lidMatchesAny(localOnly, lid))
2657
+ {
2658
+ // The lid doesn't match – suppress without clearing or printing a separator,
2659
+ // since the filter hasn't been "activated" by an accepted call yet.
2660
+ return false;
2661
+ }
2662
+
2663
+ const onlyLabel = toLabel(localOnly);
2664
+
2665
+ if (this._localOnlyFilter === undefined)
2666
+ {
2667
+ // First ever match – clear the output channel.
2668
+ if (this.isBrowser())
2669
+ {
2670
+ /* istanbul ignore next */
2671
+ ____AnaLogger.Console.clear
2672
+ ? ____AnaLogger.Console.clear()
2673
+ : (typeof console !== "undefined" && console.clear && console.clear());
2674
+ }
2675
+ else
2676
+ {
2677
+ // ANSI terminal reset: clears the screen and moves cursor to top.
2678
+ process.stdout.write("\x1bc");
2679
+ }
2680
+ }
2681
+ else if (this._localOnlyLabel !== onlyLabel)
2682
+ {
2683
+ // Filter has changed – print a separator, no clear.
2684
+ const separator = `─── only switched to ${onlyLabel} ───`;
2685
+ if (this.isBrowser())
2686
+ {
2687
+ /* istanbul ignore next */
2688
+ ____AnaLogger.Console.log(`%c${separator}`, "color: #888; font-style: italic");
2689
+ }
2690
+ else
2691
+ {
2692
+ // Use the raw console so the separator bypasses all AnaLogger formatting.
2693
+ ____AnaLogger.Console.log(separator);
2694
+ }
2695
+ }
2696
+
2697
+ this._localOnlyFilter = localOnly; // raw value – used for matching
2698
+ this._localOnlyLabel = onlyLabel; // string – used for change detection
2699
+ return true;
2700
+ }
2701
+
2585
2702
  /**
2586
2703
  * Display log following template
2587
2704
  * @param context
@@ -2612,7 +2729,7 @@ class ____AnaLogger
2612
2729
  lid: context.lid,
2613
2730
  callCount: 1,
2614
2731
  callTimes: [Date.now()]
2615
- }
2732
+ };
2616
2733
  }
2617
2734
  }
2618
2735
 
@@ -2648,6 +2765,37 @@ class ____AnaLogger
2648
2765
  return;
2649
2766
  }
2650
2767
 
2768
+ // Check if global "only" filter is active
2769
+ if (this.options.only !== undefined && this.options.only !== null) {
2770
+ const onlyFilters = Array.isArray(this.options.only) ? this.options.only : [this.options.only];
2771
+ // Check if current log matches one of the filters
2772
+ const matchesFilter = onlyFilters.some((filter) => {
2773
+ const targetLid = context.lid || "";
2774
+ const targetOnly = context.only || "";
2775
+
2776
+ if (filter instanceof RegExp) {
2777
+ return filter.test(targetLid) || filter.test(targetOnly);
2778
+ }
2779
+
2780
+ // String partial match (e.g., "API" matches "API_123")
2781
+ if (typeof filter === "string") {
2782
+ return targetLid.includes(filter) || targetOnly.includes(filter);
2783
+ }
2784
+
2785
+ return filter === targetLid || filter === targetOnly;
2786
+ });
2787
+
2788
+ if (!matchesFilter) {
2789
+ return;
2790
+ }
2791
+ }
2792
+
2793
+ // Handle the per-call local "only" option.
2794
+ if (!this.#handleLocalOnly(context))
2795
+ {
2796
+ return;
2797
+ }
2798
+
2651
2799
  const newMessages = this.checkOnLogging(context, argsWithoutContext[0], arguments,"onMessage");
2652
2800
  if (newMessages !== undefined) {
2653
2801
  arguments[1] = newMessages;
@@ -2732,9 +2880,11 @@ class ____AnaLogger
2732
2880
  }
2733
2881
  }
2734
2882
 
2735
- if (this.options.hideLog || context.hideLog || context.silent)
2736
- {
2737
- return;
2883
+ if (!(context.silent === false || context.hideLog === false)) {
2884
+ if (this.options.hideLog || context.hideLog || context.silent)
2885
+ {
2886
+ return;
2887
+ }
2738
2888
  }
2739
2889
 
2740
2890
  this.writeToConsole(output, context);
@@ -2768,6 +2918,7 @@ class ____AnaLogger
2768
2918
  options.hasOwnProperty("color") ||
2769
2919
  options.hasOwnProperty("contextName") ||
2770
2920
  options.hasOwnProperty("raw") ||
2921
+ options.hasOwnProperty("only") ||
2771
2922
  options.hasOwnProperty("lid");
2772
2923
  }
2773
2924