analogger 2.0.2 → 2.1.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.
@@ -1,2675 +0,0 @@
1
- /**
2
- * DO NOT EDIT THIS FILE DIRECTLY.
3
- * This file is generated following the conversion of
4
- * @see [./src/ana-logger.cjs]{@link ./src/ana-logger.cjs}
5
- *
6
- **/
7
- import toAnsi from "../imported/to-ansi/index.mjs";
8
- import {
9
- COLOR_TABLE, SYSTEM, MAX_CHILDREN_DOM_ANALOGGER, CLASS_REMOVED_NOTIF, ADD_TYPE, CONSOLE_AREA_CLASSNAME,
10
- PREDEFINED_FORMATS, ANALOGGER_NAME, LINE_CLASSNAME
11
- } from "./constants.mjs";
12
- import {stringify} from "../imported/flatted/esm/index.mjs";
13
- import {CONSOLE_HEADER_CLASSNAME, CONSOLE_FOOTER_CLASSNAME} from "./constants.mjs";
14
- import {anaLogger} from "../browser/ana-logger.mjs";
15
-
16
-
17
- // to-ansi is also used by the browser
18
-
19
-
20
- const DEFAULT = {
21
- moduleName: "analogger",
22
- // Default values for remote-logging
23
- protocol: "http://",
24
- host : "localhost",
25
- port : 12000,
26
- // Path for analogger text data
27
- pathname: "analogger",
28
- // Path for analogger raw data
29
- binarypathname: "uploaded",
30
- // ---------------------------------
31
- loopback: "localhost",
32
- // ---------------------------------
33
- consoleDomId: "#analogger",
34
- logFilename : "./analogger.log"
35
- };
36
-
37
-
38
-
39
- export const DEFAULT_LOG_TARGETS = {
40
- ALL : "ALL",
41
- USER: "USER"
42
- };
43
-
44
- export const DEFAULT_LOG_LEVELS = {
45
- FATAL : 5000,
46
- ERROR : 4000,
47
- WARN : 3000,
48
- INFO : 2000,
49
- LOG : 1000,
50
- DEBUG : 500,
51
- ALL : 200,
52
- OFF : 0,
53
- INHERIT: -1,
54
- };
55
-
56
- /**
57
- * @typedef PLUGIN_TYPE
58
- * @type {{LOCAL: string, GLOBAL: string}}
59
- */
60
- const PLUGIN_TYPE = {
61
- LOCAL : "local",
62
- GLOBAL: "global"
63
- };
64
-
65
- /**
66
- * @typedef PLUGIN_PROPERTIES_TYPE
67
- * @property {string} methodName AnaLogger's real method name that is set to the AnaLogger instance *
68
- * @property {function} callback AnaLogger method that will be called when invoking the plugin
69
- * @property {PLUGIN_TYPE} type Whether the plugin is accessible to the AnaLogger class or an instance
70
- */
71
-
72
- export const DEFAULT_LOG_CONTEXTS = {
73
- // The default context
74
- DEFAULT : {contextName: "DEFAULT", logLevel: DEFAULT_LOG_LEVELS.LOG, symbol: "check"},
75
- LOG : {contextName: "LOG", logLevel: DEFAULT_LOG_LEVELS.LOG, symbol: "check"},
76
- DEBUG : {contextName: "DEBUG", logLevel: DEFAULT_LOG_LEVELS.DEBUG},
77
- INFO : {contextName: "INFO", logLevel: DEFAULT_LOG_LEVELS.INFO, color: "#B18904", symbol: "diamonds"},
78
- WARN : {contextName: "WARN", logLevel: DEFAULT_LOG_LEVELS.WARN, color: COLOR_TABLE[0], symbol: "cross"},
79
- ERROR : {contextName: "ERROR", logLevel: DEFAULT_LOG_LEVELS.ERROR},
80
- CRITICAL: {contextName: "CRITICAL", logLevel: DEFAULT_LOG_LEVELS.CRITICAL},
81
- };
82
-
83
-
84
-
85
-
86
-
87
- const EOL = `
88
- `;
89
-
90
- const symbolNames = {
91
- airplane : "✈",
92
- anchor : "⚓",
93
- arrow_backward : "◀",
94
- arrow_double_up : "⏫",
95
- arrow_double_down : "⏬",
96
- arrow_forward : "▶",
97
- arrow_lower_right : "↘",
98
- arrow_lower_left : "↙",
99
- arrow_right_hook : "↪",
100
- arrow_up_down : "↕",
101
- arrow_upper_left : "↖",
102
- arrow_upper_right : "↗",
103
- ballot_box_with_check : "☑",
104
- biohazard : "☣",
105
- black_circle : "⏺",
106
- black_medium_small_square : "◾",
107
- black_medium_square : "◼",
108
- black_nib : "✒",
109
- black_small_square : "▪",
110
- black_square : "⏹",
111
- chains : "⛓",
112
- check : "✔",
113
- chess_pawn : "♟",
114
- cloud_and_rain : "⛈",
115
- clubs : "♣",
116
- coffee : "☕",
117
- copyright : "©",
118
- cross : "❌",
119
- diamonds : "♦",
120
- divisions_ign : "➗",
121
- double_triangle_right : "⏭",
122
- double_triangle_left : "⏮",
123
- email : "✉",
124
- eject : "⏏",
125
- exclamation_mark : "❗",
126
- fast_forward : "⏩",
127
- female_sign : "♀",
128
- fist : "✊",
129
- fuel_pump : "⛽",
130
- gear : "⚙",
131
- hammer_and_pick : "⚒",
132
- hand : "✋",
133
- hearts : "♥",
134
- infinity : "♾",
135
- information : "ℹ",
136
- left_right_arrow : "↔",
137
- leftwards_arrow_with_hook : "↩",
138
- male_sign : "♂",
139
- minus_sign : "➖",
140
- no_entry : "⛔",
141
- partly_sunny : "⛅",
142
- pencil : "✏",
143
- phone : "☎",
144
- plus_sign : "➕",
145
- question : "❔",
146
- radioactive : "☢",
147
- raised_hand : "✋",
148
- recycle : "♻",
149
- registered : "®",
150
- relaxed : "☺",
151
- rewind : "⏪",
152
- scissors : "✂",
153
- snowman : "☃",
154
- spades : "♠",
155
- sparkles : "✨",
156
- star : "⭐",
157
- sunny : "☀",
158
- tent : "⛺",
159
- trademark : "™",
160
- triangle_with_vertical_bar: "⏯",
161
- umbrella : "☔",
162
- vertical_bars : "⏸",
163
- watch : "⌚",
164
- white_frowning_face : "☹",
165
- white_medium_square : "◻",
166
- white_medium_small_square : "◽",
167
- white_small_square : "▫",
168
- wheelchair : "♿",
169
- white_circle : "⚪",
170
- writing_hand : "✍",
171
- };
172
-
173
- // --------------------------------------------------
174
- // Helpers
175
- // --------------------------------------------------
176
- function getFilePathProperties(filePath) {
177
- try {
178
- const ext = path.extname(filePath);
179
- const basename = path.basename(filePath, ext);
180
- const dirname = path.dirname(filePath);
181
- const fPath = filePath.slice(0, filePath.length - ext.length);
182
- return {
183
- extension: ext, filePath: fPath, basename, dirname
184
- };
185
- } catch (e) {
186
- console.error("FILEPATH_EXT_FAILURE: ", e.message);
187
- }
188
- return {
189
- extension: ".log", filePath
190
- };
191
- }
192
-
193
- function getConsistentTimestamp() {
194
- const now = new Date();
195
-
196
- // ISO 8601 format with milliseconds and timezone offset
197
- const isoString = now.toISOString();
198
-
199
- return isoString.replace(/:/g, "-").replace(/\./g, "-");
200
- }
201
-
202
- /**
203
- * Deletes all files in the given directory that match the specified filename prefix, index, and extension.
204
- *
205
- * @param {string} directory - The directory containing the files.
206
- * @param {string} filenamePrefix - The prefix of the filename (e.g., "demo").
207
- * @param {string} index - The index to match (e.g., "01", "02", "03").
208
- * @param {string} extension - The file extension (e.g., "log").
209
- * @param archiveName
210
- * @param compressionLevel
211
- * @param {function} deletionCallback - A callback function to handle the result.
212
- */
213
- function deleteFilesWithIndex(directory, filenamePrefix, index, extension, archiveName, compressionLevel, deletionCallback) {
214
- fs.readdir(directory, (err, files) => {
215
- if (err) {
216
- deletionCallback(err, null);
217
- return;
218
- }
219
-
220
- const deletedFiles = [];
221
- let filesProcessed = 0;
222
-
223
- const removeFile = (filePath, callback) => {
224
- if (!fs.existsSync(filePath)) {
225
- callback(null, null);
226
- return;
227
- }
228
- fs.unlink(filePath, (unlinkErr) => {
229
- if (unlinkErr) {
230
- console.error(`DELETION_FAILURE: Error deleting file ${filePath}: ${unlinkErr}`);
231
- } else {
232
- deletedFiles.push(filePath);
233
- }
234
- filesProcessed++;
235
- if (filesProcessed === files.length) {
236
- callback(null, deletedFiles);
237
- }
238
- });
239
- };
240
-
241
- const processFile = (file) => {
242
- if (file.startsWith(filenamePrefix + ".") && file.endsWith(index + extension)) {
243
- const filePath = path.join(directory, file);
244
-
245
- if (archiveName)
246
- {
247
- createTarGzArchiveSync(filePath, archiveName, compressionLevel);
248
- removeFile(filePath, deletionCallback);
249
- }
250
- else
251
- {
252
- removeFile(filePath, deletionCallback);
253
- }
254
-
255
- } else {
256
- filesProcessed++;
257
- if (filesProcessed === files.length) {
258
- deletionCallback(null, deletedFiles);
259
- }
260
- }
261
- };
262
-
263
- if (files.length === 0) {
264
- deletionCallback(null, deletedFiles); // Handle empty directory
265
- } else {
266
- files.forEach(processFile, compressionLevel);
267
- }
268
- });
269
- }
270
-
271
- /**
272
- * Adds a log file to a tar.gz archive.
273
- *
274
- * @param {string} inputFile - The path to the log file to be added to the archive.
275
- * @param {string} archivePath - The path to the tar.gz archive.
276
- * @param compressionLevel
277
- */
278
- function createTarGzArchiveSync(inputFile, archivePath, compressionLevel = 1) {
279
- try {
280
- // Check if the input file exists
281
- if (!fs.existsSync(inputFile)) {
282
- return;
283
- }
284
-
285
- // Create the archive if it doesn't exist, otherwise append
286
- if (!fs.existsSync(archivePath)) {
287
- // Create a new archive with the single file at root
288
- const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'tar-gz-init-'));
289
- try {
290
- const destFilePath = path.join(tempDir, path.basename(inputFile));
291
- fs.copyFileSync(inputFile, destFilePath);
292
- c({
293
- sync: true,
294
- gzip: { level: compressionLevel },
295
- file: archivePath,
296
- cwd: tempDir,
297
- portable: true,
298
- }, [path.basename(inputFile)]);
299
- } finally {
300
- fs.rmSync(tempDir, { recursive: true, force: true });
301
- }
302
- return;
303
- }
304
-
305
- // If archive exists, append
306
- const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'tar-gz-append-'));
307
-
308
- try {
309
- x({
310
- file: archivePath,
311
- cwd: tempDir,
312
- sync: true,
313
- });
314
-
315
- const destFilePath = path.join(tempDir, path.basename(inputFile));
316
- fs.copyFileSync(inputFile, destFilePath);
317
-
318
- c({
319
- gzip: true,
320
- file: archivePath,
321
- cwd: tempDir,
322
- sync: true,
323
- portable: true,
324
- }, fs.readdirSync(tempDir));
325
-
326
- } finally {
327
- fs.rmSync(tempDir, { recursive: true, force: true });
328
- }
329
- } catch (err) {
330
- console.error(`ARCHIVE_FAILURE: ${e.message}`);
331
- }
332
- }
333
-
334
- /**
335
- * https://stackoverflow.com/questions/17575790/environment-detection-node-js-or-browser
336
- * @returns {string}
337
- */
338
- function detectEnvironment()
339
- {
340
- if (typeof process === "object")
341
- {
342
- if (typeof process.versions === "object")
343
- {
344
- if (typeof process.versions.node !== "undefined")
345
- {
346
- return SYSTEM.NODE;
347
- }
348
- }
349
- }
350
- return SYSTEM.BROWSER;
351
- }
352
-
353
- const currentSystem = detectEnvironment();
354
-
355
- /**
356
- * Tell whether we are in a Node environment
357
- * @returns {boolean}
358
- */
359
- function isNode()
360
- {
361
- return currentSystem === SYSTEM.NODE;
362
- }
363
-
364
- const COMMON_METHODS = [
365
- "alert",
366
- "assert",
367
- "keepLogHistory",
368
- "getLogHistory",
369
- "truncateMessage",
370
- "truncateMessage",
371
- "rawLog",
372
- "removeOverride",
373
- "removeOverrideError",
374
- "overrideConsole",
375
- "overrideError",
376
- "table",
377
- "rawInfo",
378
- "rawWarn",
379
- "rawError",
380
- "hasSeenLid",
381
- "addToLogHistory",
382
- "releaseLogHistory",
383
- "resetLogHistory",
384
- "setLogFormat",
385
- "resetLogFormatter",
386
- "getRawLogHistory",
387
- ];
388
-
389
-
390
- /**
391
- * @module ____AnaLogger
392
- * @class ____AnaLogger
393
- */
394
- class ____AnaLogger
395
- {
396
- system = "";
397
-
398
- instanceId = "";
399
- instanceName = "";
400
-
401
- static #instances = [];
402
-
403
- logIndex = 0;
404
- logCounter = 0;
405
-
406
- #contexts = [];
407
- #targets = {};
408
- #levels = {};
409
-
410
- activeTargets = [];
411
-
412
- indexColor = 0;
413
-
414
- format = "";
415
-
416
- keepLog = false;
417
- logHistory = [];
418
-
419
- $containers = null;
420
-
421
- options = {
422
- hideHookMessage: false
423
- };
424
-
425
- static Console = null;
426
-
427
- #overridenMap = {
428
- log : false,
429
- info : false,
430
- warn : false,
431
- error: false,
432
- };
433
-
434
- static ALIGN = {
435
- LEFT : "LEFT",
436
- RIGHT: "RIGHT"
437
- };
438
-
439
- static ENVIRONMENT_TYPE = {
440
- BROWSER: "BROWSER",
441
- NODE : "NODE",
442
- OTHER : "OTHER"
443
- };
444
-
445
- static instanceCount = 0;
446
-
447
- static pluginTable = {};
448
-
449
- originalFormatFunction;
450
-
451
-
452
- constructor({name = "default"} = {})
453
- {
454
- this.system = detectEnvironment();
455
-
456
- this.format = this.onBuildLog.bind(this);
457
- this.originalFormatFunction = this.format;
458
-
459
- this.instanceName = name;
460
-
461
- this.instanceId = ____AnaLogger.instanceCount + "-" + Date.now();
462
- ____AnaLogger.#instances[____AnaLogger.instanceCount] = this;
463
- ++____AnaLogger.instanceCount;
464
-
465
- this.errorTargetHandler = this.onError.bind(this);
466
- this.errorUserTargetHandler = this.onErrorForUserTarget.bind(this);
467
-
468
- this.setOptions(this.options);
469
-
470
- if (!____AnaLogger.Console) {
471
- ____AnaLogger.Console = {
472
- log: console.log,
473
- info: console.info,
474
- warn: console.warn,
475
- error: console.error,
476
- debug: console.debug,
477
- table: console.table
478
- }
479
- }
480
-
481
- this.rawLog = ____AnaLogger.Console.log;
482
- this.rawInfo = ____AnaLogger.Console.info;
483
- this.rawWarn = ____AnaLogger.Console.warn;
484
- this.rawError = ____AnaLogger.Console.error;
485
-
486
- this.ALIGN = ____AnaLogger.ALIGN;
487
- this.ENVIRONMENT_TYPE = ____AnaLogger.ENVIRONMENT_TYPE;
488
-
489
- this.#initialiseDefault();
490
-
491
- this.resetLogHistory();
492
- }
493
-
494
- getName()
495
- {
496
- return this.instanceName;
497
- }
498
-
499
- getId()
500
- {
501
- return this.instanceId;
502
- }
503
-
504
- keepLogHistory()
505
- {
506
- this.keepLog = true;
507
- }
508
-
509
- releaseLogHistory()
510
- {
511
- this.keepLog = false;
512
- }
513
-
514
- resetLogHistory()
515
- {
516
- this.logHistory = [];
517
- }
518
-
519
- addToLogHistory(obj)
520
- {
521
- obj = obj || {};
522
- this.logHistory.push(Object.assign({}, obj));
523
- }
524
-
525
- /**
526
- * Returns log entries
527
- * @note This method should return the list of objects rather than
528
- * the array of text
529
- * @param join
530
- * @param symbol
531
- * @returns {string|*[]}
532
- */
533
- getLogHistory(join = true, symbol = EOL)
534
- {
535
- const historyLog = this.logHistory || [];
536
- const history = [];
537
- historyLog.forEach((logEntry) =>
538
- {
539
- const {text} = logEntry;
540
- history.push(text);
541
- });
542
-
543
- if (!join)
544
- {
545
- return history;
546
- }
547
-
548
- return history.join(symbol);
549
- }
550
-
551
- getRawLogHistory()
552
- {
553
- return this.logHistory || [];
554
- }
555
-
556
- hasSeenLid(lid)
557
- {
558
- this.logHistory = this.logHistory || [];
559
- for (let i = 0; i < this.logHistory.length; ++i)
560
- {
561
- const log = this.logHistory[i] || {};
562
- const context = log.context || {};
563
- if (lid === context.lid)
564
- {
565
- return true;
566
- }
567
- }
568
-
569
- return false;
570
- }
571
-
572
- forceEnvironment(system)
573
- {
574
- this.forcedSystem = system;
575
- }
576
-
577
- /**
578
- * Tell whether we are in a Node environment
579
- * @returns {boolean}
580
- */
581
- isNode()
582
- {
583
- if (this && this.forcedSystem)
584
- {
585
- return this.forcedSystem === SYSTEM.NODE;
586
- }
587
-
588
- return isNode();
589
- }
590
-
591
- /**
592
- * Tell whether the logger runs from a browser
593
- * @returns {boolean}
594
- */
595
- isBrowser()
596
- {
597
- return !this.isNode();
598
- }
599
-
600
- resetLogger()
601
- {
602
- this.options = {};
603
- this.options.timeLenMax = 12;
604
- this.options.contextLenMax = 10;
605
- this.options.idLenMax = 5;
606
- this.options.lidLenMax = 6;
607
- this.options.messageLenMax = undefined;
608
- this.options.symbolLenMax = 60;
609
- this.options.hideHookMessage = undefined;
610
- this.options.hidePassingTests = undefined;
611
- this.options.hideLog = undefined;
612
- this.options.hideError = undefined;
613
- this.options.oneConsolePerContext = true;
614
- this.options.logToDom = undefined;
615
- this.options.logToFile = undefined;
616
- this.options.logMaxSize = 0;
617
- this.options.logMaxArchives = 3;
618
- this.options.logIndexArchive = 0;
619
- this.options.logToRemote = undefined;
620
- this.options.addArchiveTimestamp = true;
621
- this.options.addArchiveIndex = true;
622
- this.options.logToRemoteUrl = undefined;
623
- this.options.logToRemoteBinaryUrl = undefined;
624
- this.options.compressArchives = false;
625
- this.options.compressionLevel = 1;
626
- this.options.protocol = undefined;
627
- this.options.host = undefined;
628
- this.options.port = undefined;
629
- this.options.pathname = undefined;
630
- this.options.binarypathname = undefined;
631
- this.options.enableDate = undefined;
632
- }
633
-
634
- resetOptions()
635
- {
636
- this.resetLogger();
637
- }
638
-
639
- setOptions({
640
- contextLenMax = 10,
641
- idLenMax = 5,
642
- lidLenMax = 6,
643
- symbolLenMax = 2,
644
- messageLenMax = undefined,
645
- hideLog = undefined,
646
- hideError = undefined,
647
- hideHookMessage = undefined,
648
- hidePassingTests = undefined,
649
- logToDom = undefined,
650
- logToFile = undefined,
651
- logMaxSize = 0,
652
- logMaxArchives = 3,
653
- logIndexArchive = 0,
654
- addArchiveTimestamp = true,
655
- addArchiveIndex = true,
656
- compressArchives = false,
657
- compressionLevel = 1,
658
- logToRemote = undefined,
659
- logToRemoteUrl = undefined,
660
- logToRemoteBinaryUrl = undefined,
661
- loopback = DEFAULT.loopback,
662
- requiredLogLevel = DEFAULT_LOG_LEVELS.LOG,
663
- oneConsolePerContext = undefined,
664
- silent = undefined,
665
- enableDate = undefined,
666
- /** Remote - all optional **/
667
- protocol = undefined,
668
- host = undefined,
669
- port = undefined,
670
- pathname = undefined,
671
- binarypathname = undefined
672
- } = null)
673
- {
674
- this.options.contextLenMax = contextLenMax;
675
- this.options.idLenMax = idLenMax;
676
- this.options.lidLenMax = lidLenMax;
677
- this.options.messageLenMax = messageLenMax;
678
- this.options.symbolLenMax = symbolLenMax;
679
-
680
- this.options.logMaxSize = logMaxSize;
681
- this.options.logMaxArchives = logMaxArchives;
682
- this.options.logIndexArchive = logIndexArchive;
683
- this.options.addArchiveTimestamp = addArchiveTimestamp;
684
- this.options.addArchiveIndex = addArchiveIndex;
685
- this.options.compressArchives = compressArchives;
686
- this.options.compressionLevel = compressionLevel;
687
-
688
- this.options.requiredLogLevel = requiredLogLevel;
689
-
690
- // TODO: Make one of silent or hideToLog options obsolete
691
- let solveSilent = undefined;
692
- if (silent !== undefined)
693
- {
694
- solveSilent = !!silent;
695
- }
696
- else if (hideLog !== undefined)
697
- {
698
- solveSilent = !!hideLog;
699
- }
700
-
701
- // Force boolean type
702
- [
703
- {hideLog: solveSilent},
704
- {oneConsolePerContext},
705
- {hideError},
706
- {enableDate},
707
- {hideHookMessage},
708
- {hidePassingTests},
709
- {logToRemote},
710
- ].forEach((feature) =>
711
- {
712
- const key = Object.keys(feature)[0];
713
- const val = feature[key];
714
- if (val !== undefined)
715
- {
716
- this.options[key] = !!val;
717
- }
718
- });
719
-
720
- // Any type
721
- [
722
- {logToRemoteBinaryUrl},
723
- {logToRemoteUrl},
724
- {loopback},
725
- {protocol},
726
- {host},
727
- {port},
728
- {pathname},
729
- {binarypathname},
730
- ].forEach((feature) =>
731
- {
732
- const key = Object.keys(feature)[0];
733
- const val = feature[key];
734
- if (val !== undefined)
735
- {
736
- this.options[key] = val;
737
- }
738
- });
739
-
740
- if (this.options.logToRemote && !this.options.logToRemoteUrl)
741
- {
742
- this.options.logToRemoteUrl = this.convertToUrl({
743
- protocol: this.options.protocol,
744
- host : this.options.host,
745
- port : this.options.port,
746
- pathname: this.options.pathname
747
- });
748
- }
749
-
750
- if (this.options.logToRemote && !this.options.logToRemoteBinaryUrl)
751
- {
752
- this.options.logToRemoteBinaryUrl = this.convertToUrl({
753
- protocol: this.options.protocol,
754
- host : this.options.host,
755
- port : this.options.port,
756
- pathname: this.options.binarypathname || DEFAULT.binarypathname
757
- });
758
- }
759
-
760
- // Special cases
761
- if (logToDom === false)
762
- {
763
- this.options.logToDom = false;
764
- }
765
- else if (logToDom !== undefined)
766
- {
767
- this.options.logToDom = (logToDom === true) ? DEFAULT.consoleDomId : logToDom;
768
- }
769
-
770
- if (logToFile === false)
771
- {
772
- this.options.logToFile = false;
773
- }
774
- else if (logToFile !== undefined)
775
- {
776
- if (!this.isBrowser())
777
- {
778
- this.options.logToFile = logToFile || DEFAULT.logFilename;
779
-
780
-
781
- }
782
-
783
- ____AnaLogger.Console.log("LogToFile is not supported in this environment. ")
784
-
785
- }
786
-
787
- }
788
-
789
- getOptions()
790
- {
791
- return this.options;
792
- }
793
-
794
- truncateMessage(input = "", {fit = 0, align = ____AnaLogger.ALIGN.LEFT, ellipsis = "..."} = {})
795
- {
796
- input = "" + input;
797
- if (fit && input.length > fit)
798
- {
799
- input = input.substring(0, fit - ellipsis.length) + ellipsis;
800
- }
801
-
802
- input = align === ____AnaLogger.ALIGN.LEFT ? input.padEnd(fit, " ") : input.padStart(fit, " ");
803
- return input;
804
- }
805
-
806
- /**
807
- * Format inputs
808
- * @see Override {@link setLogFormat}
809
- * @param contextName
810
- * @param id
811
- * @param message
812
- * @param lid
813
- * @param symbol
814
- * @returns {string}
815
- */
816
- onBuildLog({contextName, message = "", lid = "", symbol = ""} = {})
817
- {
818
- try
819
- {
820
- let strResult = "";
821
-
822
- const strs = message.split(/\n/g);
823
-
824
- for (let i = 0; i < strs.length; ++i)
825
- {
826
- let message0 = strs[i];
827
-
828
- // Time
829
- const now = new Date();
830
- let time = ("0" + now.getHours()).slice(-2) + ":" + ("0" + now.getMinutes()).slice(-2) + ":" + ("0" + now.getSeconds()).slice(-2);
831
-
832
- if (this.options.enableDate)
833
- {
834
- let date = now.getFullYear().toString().slice(-2) + "-" + (now.getMonth() + 1).toString().padStart(2, "0") + "-" + now.getDate().toString().padStart(2, "0");
835
- time = date + " " + time;
836
- }
837
-
838
- // Display content in columns
839
- time = this.truncateMessage(time, {fit: this.options.timeLenMax});
840
-
841
- if (i > 0)
842
- {
843
- contextName = "";
844
- lid = "";
845
- }
846
- contextName = this.truncateMessage(contextName, {
847
- fit : this.options.contextLenMax,
848
- align: ____AnaLogger.ALIGN.RIGHT
849
- });
850
- lid = this.truncateMessage(lid, {fit: this.options.lidLenMax});
851
-
852
- if (this.options.messageLenMax !== undefined)
853
- {
854
- message0 = this.truncateMessage(message0, {fit: this.options.messageLenMax});
855
- }
856
-
857
- symbol = this.truncateMessage(symbol, {fit: this.options.symbolLenMax});
858
-
859
- if (i <= 0)
860
- {
861
- strResult += `[${time}] ${contextName}: (${lid}) ${symbol} ${message0}`;
862
- }
863
- else
864
- {
865
- // If last line empty, don't display it
866
- if (i < strs.length - 1)
867
- {
868
- strResult += "\n";
869
- strResult += `[${time}] ${contextName} ${lid} ${message0}`;
870
- }
871
- else
872
- {
873
- if (message0)
874
- {
875
- strResult += "\n";
876
- strResult += `[${time}] ${contextName} ${lid} ${message0}`;
877
- }
878
- }
879
- }
880
- }
881
-
882
- return strResult;
883
- }
884
- catch (e)
885
- {
886
- console.rawError(e.message);
887
- }
888
-
889
- return "";
890
- }
891
-
892
- onErrorForUserTarget(context, ...args)
893
- {
894
- this.errorUserTargetHandler(context, ...args);
895
- }
896
-
897
- onError(context, ...args)
898
- {
899
- if (context.target === this.#targets.USER)
900
- {
901
- this.onErrorForUserTarget(context, ...args);
902
- }
903
- }
904
-
905
- /**
906
- * Forward input to real console log
907
- * @param args
908
- */
909
- onDisplayLog(...args)
910
- {
911
- this.log(...args);
912
- }
913
-
914
- assistStask(error)
915
- {
916
- try
917
- {
918
- const lines = error.stack.split("\n");
919
- const stack = [];
920
-
921
- for (let i = 0; i < lines.length; ++i)
922
- {
923
- const line = lines[i];
924
- stack.push(line);
925
- }
926
-
927
- return stack;
928
- }
929
- catch (e)
930
- {
931
- console.rawError(e.message);
932
- }
933
-
934
- return error.message;
935
- }
936
-
937
- /**
938
- * Forward input to real console log
939
- * @param args
940
- */
941
- onDisplayError(...args)
942
- {
943
- try
944
- {
945
- let mainIndex = -1;
946
- let extracted = null;
947
- for (let i = 0; i < args.length; ++i)
948
- {
949
- const arg = args[i];
950
- if (arg instanceof Error)
951
- {
952
- if (arg.stack)
953
- {
954
- mainIndex = i;
955
- extracted = this.assistStask(arg) || [];
956
- break;
957
- }
958
- }
959
- }
960
-
961
- if (!extracted)
962
- {
963
- this.error(...args);
964
- return;
965
- }
966
-
967
- for (let i = 0; i < extracted.length; ++i)
968
- {
969
- args[mainIndex] = extracted[i];
970
- this.error(...args);
971
- }
972
-
973
- }
974
- catch (e)
975
- {
976
- console.rawError(e);
977
- }
978
-
979
- }
980
-
981
- /**
982
- * Set log template
983
- * @param format
984
- */
985
- setLogFormat(format)
986
- {
987
- if (typeof format !== "function")
988
- {
989
- console.error("Invalid parameter for setFormat. It is expecting a function or method.");
990
- return false;
991
- }
992
- this.format = format.bind(this);
993
- }
994
-
995
- resetLogFormatter()
996
- {
997
- this.format = this.originalFormatFunction;
998
- }
999
-
1000
- setErrorHandler(handler)
1001
- {
1002
- this.errorTargetHandler = handler.bind(this);
1003
- }
1004
-
1005
- setErrorHandlerForUserTarget(handler)
1006
- {
1007
- this.errorUserTargetHandler = handler.bind(this);
1008
- }
1009
-
1010
- // ------------------------------------------------
1011
- // Color
1012
- // ------------------------------------------------
1013
-
1014
- // ------------------------------------------------
1015
- // Log Contexts
1016
- // ------------------------------------------------
1017
- isContextValid(context)
1018
- {
1019
- if (
1020
- !(typeof context === "object" &&
1021
- !Array.isArray(context) &&
1022
- context !== null)
1023
- )
1024
- {
1025
- return false;
1026
- }
1027
- return (context.hasOwnProperty("contextName") && context.hasOwnProperty("target"));
1028
- }
1029
-
1030
- /**
1031
- * Set context properties for default context
1032
- * @param context
1033
- */
1034
- setDefaultContext(context)
1035
- {
1036
- this.setContext(DEFAULT_LOG_CONTEXTS.DEFAULT.contextName, context);
1037
- }
1038
-
1039
- /**
1040
- * Generate a default context with a default color
1041
- * @returns {*|{}}
1042
- */
1043
- generateDefaultContext()
1044
- {
1045
- let defaultContext = this.#contexts[DEFAULT_LOG_CONTEXTS.DEFAULT.contextName] || {};
1046
- defaultContext = Object.assign({},
1047
- {
1048
- lid : "",
1049
- contextName: DEFAULT_LOG_CONTEXTS.DEFAULT.contextName,
1050
- target : DEFAULT_LOG_TARGETS.ALL,
1051
- symbol : "⚡",
1052
- color : COLOR_TABLE[1],
1053
- logLevel : DEFAULT_LOG_LEVELS.LOG
1054
- }, defaultContext);
1055
-
1056
- defaultContext.name = defaultContext.contextName;
1057
-
1058
- defaultContext.id = this.logIndex++;
1059
- return defaultContext;
1060
- }
1061
-
1062
- /**
1063
- * Generate a new context based on the default context.
1064
- * The only difference with default is that a different color will be assigned to that context automatically
1065
- * @returns {*|{}}
1066
- */
1067
- generateNewContext()
1068
- {
1069
- const newContext = this.generateDefaultContext();
1070
- newContext.color = COLOR_TABLE[(this.indexColor++) % (COLOR_TABLE.length - 3) + 2];
1071
- newContext.symbol = "";
1072
- return newContext;
1073
- }
1074
-
1075
- generateErrorContext()
1076
- {
1077
- const errorContext = this.generateDefaultContext();
1078
- errorContext.contextName = DEFAULT_LOG_CONTEXTS.ERROR.contextName;
1079
- errorContext.name = errorContext.contextName;
1080
- errorContext.color = COLOR_TABLE[0];
1081
- errorContext.symbol = "❌";
1082
- errorContext.error = true;
1083
- errorContext.logLevel = DEFAULT_LOG_LEVELS.ERROR;
1084
- return errorContext;
1085
- }
1086
-
1087
- /**
1088
- * Use given context to generate new context
1089
- * @param entry
1090
- * @returns {any}
1091
- */
1092
- #defineContextProperties(entry)
1093
- {
1094
- const defaultContext = this.generateNewContext();
1095
- const converted = Object.assign({}, defaultContext, entry);
1096
- if (converted.color.toLowerCase().indexOf("rgb") > -1)
1097
- {
1098
- converted.color = toAnsi.rgbStringToHex(converted.color);
1099
- }
1100
- else if (converted.color.indexOf("#") === -1)
1101
- {
1102
- converted.color = toAnsi.colorNameToHex(converted.color);
1103
- }
1104
-
1105
- return converted;
1106
- }
1107
-
1108
- /**
1109
- * Redefine a context
1110
- * @param contextName
1111
- * @param context
1112
- */
1113
- setContext(contextName, context = {})
1114
- {
1115
- context.contextName = contextName;
1116
- context.name = contextName;
1117
- context = this.#defineContextProperties(context);
1118
- this.#contexts[contextName] = context;
1119
- }
1120
-
1121
- getContext(contextName)
1122
- {
1123
- return this.#contexts[contextName];
1124
- }
1125
-
1126
- /**
1127
- * Load the context names that should be available to the environment.
1128
- * They are defined by the user.
1129
- * @see Context definitions {@link ./example/more/contexts-def.cjs}
1130
- * @param contextTable
1131
- */
1132
- setContexts(contextTable)
1133
- {
1134
- const arr = Object.keys(contextTable);
1135
- arr.forEach((contextName) =>
1136
- {
1137
- const contextPassed = contextTable[contextName] || {};
1138
- this.setContext(contextName, contextPassed);
1139
- contextTable[contextName] = this.#contexts[contextName];
1140
- });
1141
- }
1142
-
1143
- getContexts()
1144
- {
1145
- return Object.freeze(this.#contexts);
1146
- }
1147
-
1148
- setTargets(targetTable = {})
1149
- {
1150
- let targetObjects = {};
1151
- if (Array.isArray(targetTable))
1152
- {
1153
- try
1154
- {
1155
- for (let i = 0; i < targetTable.length; ++i)
1156
- {
1157
- const entry = targetTable[i];
1158
- if (typeof entry === "string" || entry instanceof String)
1159
- {
1160
- targetObjects[entry] = entry;
1161
- }
1162
- else if (typeof entry === "object")
1163
- {
1164
- let found = null;
1165
- for (let prop in entry)
1166
- {
1167
- let valueProp = entry[prop];
1168
- prop = prop.trim();
1169
- if (!prop)
1170
- {
1171
- console.error(`Invalid target`);
1172
- break;
1173
- }
1174
-
1175
- if (typeof valueProp === "string" || valueProp instanceof String)
1176
- {
1177
- valueProp = valueProp.trim();
1178
- found = [prop, valueProp];
1179
- break;
1180
- }
1181
-
1182
- if (typeof valueProp === "number")
1183
- {
1184
- break;
1185
- }
1186
-
1187
- }
1188
-
1189
- if (found)
1190
- {
1191
- targetObjects[found[0]] = found[1];
1192
- }
1193
-
1194
- }
1195
-
1196
- }
1197
- }
1198
- catch (e)
1199
- {
1200
- console.error({lid: 4321}, e.message);
1201
- }
1202
- }
1203
- else
1204
- {
1205
- targetObjects = targetTable;
1206
- }
1207
-
1208
- this.#targets = Object.assign({}, targetObjects, {...DEFAULT_LOG_TARGETS});
1209
- }
1210
-
1211
- addTargets(targets)
1212
- {
1213
- const currentTargets = this.#targets;
1214
- const merged = Object.assign({}, currentTargets, targets);
1215
- this.setTargets(merged);
1216
- }
1217
-
1218
- getTargets()
1219
- {
1220
- return Object.freeze(this.#targets);
1221
- }
1222
-
1223
- /**
1224
- * Set one or more active targets
1225
- * @param targets
1226
- */
1227
- setActiveTargets(targets = null)
1228
- {
1229
- if (targets === null)
1230
- {
1231
- this.activeTargets = [DEFAULT_LOG_TARGETS.ALL];
1232
- return;
1233
- }
1234
- else if (typeof targets === "string" || targets instanceof String)
1235
- {
1236
- targets = targets.split(",");
1237
- }
1238
- else if (typeof targets === "object" || typeof targets === "function")
1239
- {
1240
- return;
1241
- }
1242
-
1243
- for (let i = 0; i < targets.length; ++i)
1244
- {
1245
- targets[i] = targets[i].trim();
1246
- }
1247
-
1248
- this.activeTargets = targets;
1249
- }
1250
-
1251
- getActiveTarget()
1252
- {
1253
- return this.activeTargets;
1254
- }
1255
-
1256
- /**
1257
- * Set only one active target
1258
- * NOTE: Kept for backward compatibility.
1259
- * Use setActiveTargets instead
1260
- * @param target
1261
- */
1262
- setActiveTarget(target)
1263
- {
1264
- this.activeTargets = [];
1265
- this.setActiveTargets(target);
1266
- // In case of strings
1267
- this.activeTargets = [this.activeTargets[0]];
1268
- }
1269
-
1270
- setLogLevel(name, level)
1271
- {
1272
- this.#levels[name] = level;
1273
- }
1274
-
1275
- getLogLevel(name)
1276
- {
1277
- return this.#levels[name];
1278
- }
1279
-
1280
- setLogLevels(levels)
1281
- {
1282
- this.#levels = levels;
1283
- }
1284
-
1285
- getLogLevels()
1286
- {
1287
- return Object.freeze(this.#levels);
1288
- }
1289
-
1290
- isTargetAllowed(target)
1291
- {
1292
- // If target or activeTargets undefined, allow everything
1293
- if (!target || !this.activeTargets || !this.activeTargets.length)
1294
- {
1295
- return true;
1296
- }
1297
-
1298
- if (target === DEFAULT_LOG_TARGETS.ALL)
1299
- {
1300
- return true;
1301
- }
1302
-
1303
- if (this.activeTargets.includes(DEFAULT_LOG_TARGETS.ALL))
1304
- {
1305
- return true;
1306
- }
1307
-
1308
- return this.activeTargets.includes(target);
1309
- }
1310
-
1311
-
1312
- // ------------------------------------------------
1313
- // Logging methods
1314
- // ------------------------------------------------
1315
- /**
1316
- * Add many sections (columns) to a given DOM line
1317
- * @param $line
1318
- * @param context
1319
- * @param text
1320
- */
1321
- setColumns($line, context, text)
1322
- {
1323
- let index = 0;
1324
- for (let columnName in context)
1325
- {
1326
- if (!["contextName", "symbol", "lid", "text"].includes(columnName))
1327
- {
1328
- continue;
1329
- }
1330
-
1331
- const colContent = context[columnName];
1332
- const $col = document.createElement("span");
1333
- $col.classList.add("analogger-col", `analogger-col-${columnName}`, `analogger-col-${index}`);
1334
- ++index;
1335
- $col.textContent = colContent;
1336
- $line.append($col);
1337
- }
1338
-
1339
- let $col = document.createElement("span");
1340
- $col.classList.add("analogger-col", "analogger-col-text", `analogger-col-${index}`);
1341
- $col.textContent = text;
1342
- $line.append($col);
1343
-
1344
- // Add 3 more columns
1345
- for (let i = 1; i <= 3; ++i)
1346
- {
1347
- $col = document.createElement("span");
1348
- $col.classList.add("analogger-col", "analogger-col-extra", `analogger-extra-${i}`);
1349
- $line.append($col);
1350
- }
1351
- }
1352
-
1353
- /**
1354
- * Check that the div has not too many entries
1355
- * @param $view
1356
- */
1357
- removeDomOldEntries = ($view) =>
1358
- {
1359
- const nbChildren = $view.childElementCount;
1360
- if (nbChildren > MAX_CHILDREN_DOM_ANALOGGER)
1361
- {
1362
- const n = Math.ceil(MAX_CHILDREN_DOM_ANALOGGER / 10);
1363
- for (let i = 0; i < n; ++i)
1364
- {
1365
- $view.removeChild($view.firstChild);
1366
- }
1367
- return n;
1368
- }
1369
-
1370
- return 0;
1371
- };
1372
-
1373
- /**
1374
- * Scroll to bottom if div is already at the bottom
1375
- * @param $view
1376
- */
1377
- scrollDivToBottom = ($view) =>
1378
- {
1379
- const scrollBottom = $view.scrollHeight - ($view.clientHeight + $view.scrollTop);
1380
- const divHeight = $view.clientHeight || $view.offsetHeight;
1381
- if (scrollBottom > divHeight / 2)
1382
- {
1383
- /* istanbul ignore next */
1384
- return;
1385
- }
1386
-
1387
- $view.scrollTop = $view.scrollHeight;
1388
- };
1389
-
1390
- checkOnLoggingToDom(context, param2)
1391
- {
1392
- try
1393
- {
1394
- let callback = context.onLoggingToDom;
1395
- if (typeof callback !== "function")
1396
- {
1397
- return;
1398
- }
1399
-
1400
- return callback.call(this, context, param2);
1401
- }
1402
- catch (e)
1403
- {
1404
- }
1405
- }
1406
-
1407
- /**
1408
- * Add a line to the Analogger div.
1409
- * Remove older lines if exceeding limit.
1410
- * @param $view
1411
- * @param $line
1412
- * @param context
1413
- * @param addType
1414
- * @param message
1415
- * @param text
1416
- * @param args
1417
- */
1418
- addLineToDom($view, $line, {context, addType, message, text, args})
1419
- {
1420
- let proceedFurther = this.checkOnLoggingToDom(context, {
1421
- message,
1422
- text,
1423
- args,
1424
- logCounter: this.logCounter,
1425
- $view,
1426
- $line,
1427
- addType
1428
- });
1429
-
1430
- // If one of the plugins returns false, no further operation will follow
1431
- if (proceedFurther === false)
1432
- {
1433
- return;
1434
- }
1435
-
1436
- if (addType === ADD_TYPE.BOTTOM)
1437
- {
1438
- $view.append($line);
1439
- }
1440
- else
1441
- {
1442
- $view.insertBefore($line, $view.firstChild);
1443
- }
1444
-
1445
- let nbRemoved = this.removeDomOldEntries($view);
1446
- if (nbRemoved)
1447
- {
1448
- if ($view.getElementsByClassName(CLASS_REMOVED_NOTIF).length)
1449
- {
1450
- return;
1451
- }
1452
-
1453
- this.showRemovedNotification(context);
1454
- return;
1455
- }
1456
-
1457
- this.scrollDivToBottom($view);
1458
-
1459
- }
1460
-
1461
- showRemovedNotification(context)
1462
- {
1463
- context.contextName = ANALOGGER_NAME;
1464
- context.symbol = "🗑";
1465
- context.color = "orange";
1466
- context.className = CLASS_REMOVED_NOTIF;
1467
-
1468
- clearTimeout(this.timerAddLineToDomID);
1469
- this.timerAddLineToDomID = setTimeout(() =>
1470
- {
1471
- this.timerAddLineToDomID = null;
1472
- /* istanbul ignore next */
1473
- this.writeLogToDom(context, "", {addType: ADD_TYPE.TOP, message: `Oldest entries removed`});
1474
- }, 500);
1475
- }
1476
-
1477
- writeLogToDom(context, fullText, {addType = ADD_TYPE.BOTTOM, message = "", args = null} = {})
1478
- {
1479
- this.$containers = this.$containers || document.querySelectorAll(this.options.logToDom);
1480
- fullText = message || fullText;
1481
-
1482
- for (let i = 0; i < this.$containers.length; ++i)
1483
- {
1484
- const $container = this.$containers[i];
1485
-
1486
- let $header = $container.querySelector("." + CONSOLE_HEADER_CLASSNAME);
1487
- if (!$header)
1488
- {
1489
- $header = document.createElement("div");
1490
- $header.classList.add(CONSOLE_HEADER_CLASSNAME);
1491
-
1492
- $header.append(document.createElement("span"));
1493
- $header.append(document.createElement("span"));
1494
- $header.append(document.createElement("span"));
1495
-
1496
- $container.append($header);
1497
- }
1498
-
1499
- let $view = $container.querySelector("." + CONSOLE_AREA_CLASSNAME);
1500
- if (!$view)
1501
- {
1502
- $view = document.createElement("div");
1503
- $view.classList.add(CONSOLE_AREA_CLASSNAME);
1504
- $container.append($view);
1505
- }
1506
-
1507
- let $footer = $container.querySelector("." + CONSOLE_FOOTER_CLASSNAME);
1508
- if (!$footer)
1509
- {
1510
- $footer = document.createElement("div");
1511
- $footer.classList.add(CONSOLE_FOOTER_CLASSNAME);
1512
-
1513
- $footer.append(document.createElement("span"));
1514
- $footer.append(document.createElement("span"));
1515
- $footer.append(document.createElement("span"));
1516
-
1517
- $container.append($footer);
1518
- }
1519
-
1520
- const $line = document.createElement("div");
1521
- $line.classList.add(LINE_CLASSNAME);
1522
- if (context.className)
1523
- {
1524
- $line.classList.add(context.className);
1525
- }
1526
- $line.style.color = context.color;
1527
-
1528
- this.setColumns($line, context, fullText, args);
1529
-
1530
- // Prevent the application to be stuck when many logs are entered at once
1531
- /* istanbul ignore next */
1532
- setTimeout(/* istanbul ignore next */function ($view, $line, {addType, context, message, text, args})
1533
- {
1534
- /* istanbul ignore next */
1535
- this.addLineToDom($view, $line, {addType, context, message, text, args});
1536
- }.bind(this, $view, $line, {addType, context, message, text: fullText, args}), 0);
1537
-
1538
- }
1539
- }
1540
-
1541
- writeLogToFile(text)
1542
- {
1543
- try
1544
- {
1545
- if (!fs.existsSync(this.options.logToFilePath))
1546
- {
1547
- const dir = path.dirname(this.options.logToFilePath);
1548
- if (!fs.existsSync(dir))
1549
- {
1550
- fs.mkdirSync(dir, { recursive: true });
1551
- }
1552
- fs.writeFileSync(this.options.logToFilePath, "");
1553
- }
1554
-
1555
- // Check filesize doesn't exceed the limit set by the user
1556
- if (this.options.logMaxSize) {
1557
- const stats = fs.statSync(this.options.logToFilePath);
1558
- const fileSizeInBytes = stats.size;
1559
- if (fileSizeInBytes > this.options.logMaxSize) {
1560
-
1561
- if (this.options.logIndexArchive < this.options.logMaxArchives) {
1562
- ++this.options.logIndexArchive;
1563
- } else {
1564
- this.options.logIndexArchive = 1;
1565
- }
1566
-
1567
- // Extract the archive name without the extension
1568
- const padding = this.options.logMaxArchives.toString().length + 1;
1569
- const {filePath, extension, basename, dirname} = getFilePathProperties(this.options.logToFilePath);
1570
-
1571
- // Find index of the next archive
1572
- let indexStr, timeStamp;
1573
- indexStr = this.options.addArchiveIndex ? "." + this.options.logIndexArchive.toString().padStart(padding, "0") : "";
1574
- timeStamp = this.options.addArchiveTimestamp ? "." + getConsistentTimestamp() : "";
1575
-
1576
- // Deduce old log file name
1577
- const oldFileName = `${filePath}${timeStamp}${indexStr}${extension}`;
1578
-
1579
- // Deduce archive name
1580
- const archiveFileName = this.options.compressArchives ? `${filePath}.tar.gz` : "";
1581
-
1582
- // Delete old archives
1583
- deleteFilesWithIndex(dirname, basename, indexStr, extension, archiveFileName, this.options.compressionLevel, (error/*, deletedFiles*/) => {
1584
- if (error) {
1585
- console.error(`DELETION_FAILURE: Failed to delete some files`);
1586
- }
1587
- });
1588
-
1589
- fs.renameSync(this.options.logToFilePath, oldFileName);
1590
- fs.writeFileSync(this.options.logToFilePath, "");
1591
- }
1592
- }
1593
- fs.appendFileSync(this.options.logToFilePath, text + this.EOL);
1594
- } catch (e) {
1595
- /* istanbul ignore next */
1596
- console.rawError("LOG_TO_FILE_FAILURE: ", e.message);
1597
- }
1598
- }
1599
-
1600
- writeLogToRemote(...data)
1601
- {
1602
- try
1603
- {
1604
- const urlDest = this.generateLogToRemoteUrl(this.options.logToRemoteUrl);
1605
- if (!urlDest)
1606
- {
1607
- return null;
1608
- }
1609
-
1610
- const entry = [...data];
1611
- const stringified = JSON.stringify(entry);
1612
- fetch(urlDest, {
1613
- method : "post",
1614
- body : stringified,
1615
- headers: {"Content-Type": "application/json"},
1616
- })
1617
- .then(res => res.json())
1618
- .catch(() => null);
1619
- }
1620
- catch (e)
1621
- {
1622
- /* istanbul ignore next */
1623
- console.rawError("LOG_TO_REMOTE_FAILURE: ", e.message);
1624
- }
1625
- }
1626
-
1627
- /**
1628
- * Send data to the registered remote server
1629
- * @param raw
1630
- * @param context
1631
- * @param done
1632
- */
1633
- uploadDataToRemote(raw, context = null, done = null)
1634
- {
1635
- try
1636
- {
1637
- if (!this.options.logToRemote)
1638
- {
1639
- return;
1640
- }
1641
-
1642
- const urlDest = this.generateLogToRemoteUrl(this.options.logToRemoteBinaryUrl, {pathname: DEFAULT.binarypathname});
1643
- if (!urlDest)
1644
- {
1645
- return null;
1646
- }
1647
-
1648
- let data = raw;
1649
- if (context)
1650
- {
1651
- data = JSON.stringify({raw, context});
1652
- }
1653
-
1654
- fetch(urlDest, {
1655
- method: "post",
1656
- body : data,
1657
- })
1658
- .then((response) => response.json())
1659
- .then((data) => done && done(data))
1660
- .catch(e => e);
1661
- }
1662
- catch (e)
1663
- {
1664
- /* istanbul ignore next */
1665
- console.rawError("BINARY_TO_REMOTE_FAILURE: ", e.message);
1666
- }
1667
- }
1668
-
1669
- stringifyEntry(arg)
1670
- {
1671
- let str;
1672
-
1673
- try
1674
- {
1675
- str = JSON.stringify(arg);
1676
- }
1677
- catch (e)
1678
- {
1679
-
1680
- }
1681
-
1682
- if (!str)
1683
- {
1684
- try
1685
- {
1686
- str = stringify(arg);
1687
- }
1688
- catch (e)
1689
- {
1690
-
1691
- }
1692
- }
1693
-
1694
- return str;
1695
- }
1696
-
1697
- /**
1698
- * If a variable is too complex for the logger, stringify it
1699
- */
1700
- convertEntry(arg)
1701
- {
1702
- try
1703
- {
1704
- if (arg === null || arg === undefined || arg === "")
1705
- {
1706
- return arg;
1707
- }
1708
- else if (typeof arg === "boolean")
1709
- {
1710
- return arg;
1711
- }
1712
- else if (typeof arg === "symbol")
1713
- {
1714
- return arg;
1715
- }
1716
- if (typeof arg === "number")
1717
- {
1718
- return arg;
1719
- }
1720
- else if (typeof arg === "string" || myVar instanceof arg)
1721
- {
1722
- return arg;
1723
- }
1724
- else if (arg instanceof Date)
1725
- {
1726
- return arg;
1727
- }
1728
- }
1729
- catch (e)
1730
- {
1731
- }
1732
-
1733
- return this.stringifyEntry(arg);
1734
- }
1735
-
1736
- convertArgumentsToText(args)
1737
- {
1738
- const strs = [];
1739
- let text;
1740
- const n = args.length;
1741
- for (let i = 0; i < n; ++i)
1742
- {
1743
- let str;
1744
- let arg = args[i];
1745
-
1746
- str = this.convertEntry(arg);
1747
-
1748
- strs.push(str);
1749
- }
1750
-
1751
- text = strs.join("•");
1752
- return text;
1753
- }
1754
-
1755
- writeToConsole(output, context)
1756
- {
1757
- const res = [output];
1758
- if (this.isBrowser())
1759
- {
1760
- res.push(`color: ${context.color}`);
1761
- }
1762
-
1763
- const contextLevel = context.contextLevel || DEFAULT_LOG_LEVELS.LOG;
1764
- if (contextLevel >= DEFAULT_LOG_LEVELS.ERROR)
1765
- {
1766
- ____AnaLogger.Console.error(...res);
1767
- }
1768
- else if (contextLevel >= DEFAULT_LOG_LEVELS.WARN)
1769
- {
1770
- ____AnaLogger.Console.warn(...res);
1771
- }
1772
- else if (contextLevel >= DEFAULT_LOG_LEVELS.INFO)
1773
- {
1774
- ____AnaLogger.Console.info(...res);
1775
- }
1776
- else if (contextLevel >= DEFAULT_LOG_LEVELS.LOG)
1777
- {
1778
- ____AnaLogger.Console.log(...res);
1779
- }
1780
- else if (contextLevel >= DEFAULT_LOG_LEVELS.DEBUG)
1781
- {
1782
- ____AnaLogger.Console.debug(...res);
1783
- }
1784
-
1785
- }
1786
-
1787
- /**
1788
- * Parse the context. If one of its keys has the same name as a registered plugin,
1789
- * the system will invoke the plugin (the value of the key must be anything truthy).
1790
- * @param context
1791
- * @param extras
1792
- * @returns {undefined|boolean}
1793
- */
1794
- checkPlugins(context, {message, text, args, logCounter})
1795
- {
1796
- try
1797
- {
1798
- if (!Object.keys(____AnaLogger.pluginTable).length)
1799
- {
1800
- return;
1801
- }
1802
-
1803
- let proceedFurther = true;
1804
- for (let keyName in context)
1805
- {
1806
- const pluginOptions = context[keyName];
1807
-
1808
- /**
1809
- * The key has been passed in the context, but has a falsy value,
1810
- * so let's ignore it
1811
- */
1812
- if (!pluginOptions)
1813
- {
1814
- continue;
1815
- }
1816
-
1817
- /**
1818
- * Extract plugin properties
1819
- * @type PLUGIN_TYPE
1820
- */
1821
- const pluginProperties = ____AnaLogger.pluginTable[keyName];
1822
-
1823
- /**
1824
- * Check plugin properties exists
1825
- * @see addPlugin
1826
- * @see addGlobalPlugin
1827
- */
1828
- if (!pluginProperties)
1829
- {
1830
- continue;
1831
- }
1832
-
1833
- // Should be an object
1834
- if (typeof pluginProperties !== "object")
1835
- {
1836
- continue;
1837
- }
1838
-
1839
- /**
1840
- * Extract plugin properties
1841
- */
1842
- const {callback, methodName, type} = pluginProperties;
1843
- if (typeof callback !== "function")
1844
- {
1845
- continue;
1846
- }
1847
-
1848
- /**
1849
- * Invoke the plugin
1850
- */
1851
- let res = callback.call(this, context, {
1852
- message,
1853
- text,
1854
- args,
1855
- logCounter,
1856
- methodName,
1857
- type,
1858
- pluginOptions
1859
- });
1860
-
1861
- // If the plugin returns exactly false, the log entry will be ignored by anaLogger
1862
- if (res === false)
1863
- {
1864
- proceedFurther = false;
1865
- }
1866
- }
1867
- return proceedFurther;
1868
- }
1869
- catch (e)
1870
- {
1871
- }
1872
- }
1873
-
1874
- /**
1875
- * If the context contain a key onLogging that is a function,
1876
- * execute
1877
- * @param context
1878
- * @param data
1879
- * @param extras
1880
- * @param callbackName
1881
- * @returns {*}
1882
- */
1883
- checkOnLogging(context, data, extras, callbackName )
1884
- {
1885
- if (!callbackName) {
1886
- return ;
1887
- }
1888
- try
1889
- {
1890
- let callback = context[callbackName];
1891
- if (typeof callback !== "function")
1892
- {
1893
- return;
1894
- }
1895
-
1896
- return callback.call(this, data, extras);
1897
- }
1898
- catch (e)
1899
- {
1900
- }
1901
- }
1902
-
1903
- /**
1904
- * Display log following template
1905
- * @param context
1906
- */
1907
- processOutput(context = {})
1908
- {
1909
- try
1910
- {
1911
- let message = "";
1912
- this.applySymbolByName(context);
1913
-
1914
- this.checkOnLogging(context, context, arguments, "onContext");
1915
- if (!this.isTargetAllowed(context.target))
1916
- {
1917
- return;
1918
- }
1919
-
1920
- if (context.logLevel === DEFAULT_LOG_LEVELS.OFF)
1921
- {
1922
- return;
1923
- }
1924
-
1925
- if (this.options.requiredLogLevel > context.logLevel)
1926
- {
1927
- return;
1928
- }
1929
-
1930
- // Clone arguments without the context (= the first argument passed) to generate the message
1931
- const newMessages = this.checkOnLogging(context, arguments && arguments.length > 1? arguments[1] : arguments, arguments,"onMessage");
1932
- if (newMessages !== undefined) {
1933
- arguments[1] = newMessages;
1934
- }
1935
- let args = Array.prototype.slice.call(arguments, 1 /* => Ignore arguments[0] = context */);
1936
-
1937
- message = this.convertArgumentsToText(args);
1938
-
1939
- let output = "";
1940
- let text = this.format({...context, message});
1941
-
1942
- if (this.keepLog)
1943
- {
1944
- this.addToLogHistory({context, message, text});
1945
- }
1946
-
1947
- ++this.logCounter;
1948
-
1949
- let proceedFurther = this.checkOnLogging(context, text, {message, args, logCounter: this.logCounter}, "onOutput");
1950
- // If one of the plugins returns false, no further operation will follow
1951
- if (proceedFurther === false)
1952
- {
1953
- return;
1954
- }
1955
- else if (typeof proceedFurther === 'string' || proceedFurther instanceof String)
1956
- {
1957
- text = proceedFurther;
1958
- }
1959
-
1960
- proceedFurther = this.checkPlugins(context, {message, text, args, logCounter: this.logCounter});
1961
-
1962
- // If one of the plugins returns false, no further operation will follow
1963
- if (proceedFurther === false)
1964
- {
1965
- return;
1966
- }
1967
-
1968
- if (this.options.logToRemote)
1969
- {
1970
- this.writeLogToRemote(context, ...args);
1971
- }
1972
-
1973
- /* istanbul ignore next */
1974
- if (this.isBrowser())
1975
- {
1976
- context.environnment = ____AnaLogger.ENVIRONMENT_TYPE.BROWSER;
1977
- /* istanbul ignore next */
1978
- if (this.options.logToDom)
1979
- {
1980
- /* istanbul ignore next */
1981
- this.writeLogToDom(context, text, {message, args,});
1982
- }
1983
-
1984
- output = `%c${text}`;
1985
- }
1986
- else
1987
- {
1988
- context.environnment = ____AnaLogger.ENVIRONMENT_TYPE.NODE;
1989
- output = toAnsi.getTextFromColor(text, {
1990
- fg : context.color,
1991
- bg : context.bgColor,
1992
- isBold : context.bold,
1993
- isUnderline: context.underline,
1994
- isReversed : context.reversed
1995
- });
1996
-
1997
- if (this.options.logToFile)
1998
- {
1999
- this.writeLogToFile(text);
2000
- }
2001
- }
2002
-
2003
- if (this.options.hideLog || context.hideLog || context.silent)
2004
- {
2005
- return;
2006
- }
2007
-
2008
- this.writeToConsole(output, context);
2009
-
2010
- this.errorTargetHandler(context, args);
2011
- }
2012
- catch (e)
2013
- {
2014
- /* istanbul ignore next */
2015
- console.rawError("AnaLogger:", e.message);
2016
- }
2017
- }
2018
-
2019
- /**
2020
- * Check that a parameter uses the expected AnaLogger format.
2021
- * For this, the first parameter should be an object that contains at least
2022
- * a logging id (lid), a target, a contextName, etc
2023
- * @param options
2024
- * @returns {boolean}
2025
- */
2026
- isExtendedOptionsPassed(options)
2027
- {
2028
- if (typeof options !== "object")
2029
- {
2030
- return false;
2031
- }
2032
-
2033
- return options.hasOwnProperty("context") ||
2034
- options.hasOwnProperty("target") ||
2035
- options.hasOwnProperty("color") ||
2036
- options.hasOwnProperty("contextName") ||
2037
- options.hasOwnProperty("raw") ||
2038
- options.hasOwnProperty("lid");
2039
- }
2040
-
2041
- /**
2042
- * Convert a string into a Context object if possible
2043
- * TODO: To implement in next version
2044
- * @param str
2045
- * @returns {string}
2046
- */
2047
- extractContextFromInput(str)
2048
- {
2049
- if (typeof str === "string" || str instanceof String)
2050
- {
2051
- if (str.toLowerCase().indexOf("lid:") !== 0)
2052
- {
2053
- return str;
2054
- }
2055
- }
2056
-
2057
- return str;
2058
- }
2059
-
2060
- listSymbols()
2061
- {
2062
- for (let key in symbolNames)
2063
- {
2064
- console.rawLog(symbolNames[key] + ` ${key} `);
2065
- }
2066
- }
2067
-
2068
- applySymbolByName(context)
2069
- {
2070
- try
2071
- {
2072
- if (context.symbol && symbolNames[context.symbol])
2073
- {
2074
- context.symbol = symbolNames[context.symbol];
2075
- }
2076
- }
2077
- catch (e)
2078
- {
2079
-
2080
- }
2081
- }
2082
-
2083
- /**
2084
- * Convert the first parameter of a console.log to a Context object
2085
- * @param options
2086
- * @param defaultContext
2087
- * @returns {*|{}}
2088
- */
2089
- convertToContext(options, defaultContext)
2090
- {
2091
- options = options || defaultContext;
2092
-
2093
- let context = options;
2094
-
2095
- // Flatten option object. For instance,
2096
- // {something: "some1", something2: "some2", context: {lid: 3000, color: "purple"}}
2097
- // Will become {something: "some1", something2: "some2", lid: 3000, color: "purple"}
2098
- if (options.context && typeof options.context === "object")
2099
- {
2100
- const moreOptions = Object.assign({}, options);
2101
- delete moreOptions.context;
2102
- context = Object.assign({}, options.context, moreOptions);
2103
- }
2104
-
2105
- context = Object.assign({}, defaultContext, context);
2106
- delete context.context;
2107
-
2108
- return context;
2109
- }
2110
-
2111
- /**
2112
- * console.log with options set on the first parameter to dictate console log behaviours
2113
- * @param options
2114
- * @param args
2115
- */
2116
- log(options, ...args)
2117
- {
2118
- options = this.extractContextFromInput(options);
2119
- // If the first parameter is not of context format,
2120
- // We use the default context and display
2121
- if (!this.isExtendedOptionsPassed(options))
2122
- {
2123
- const defaultContext = this.generateDefaultContext();
2124
- this.processOutput.apply(this, [defaultContext, options, ...args]);
2125
- return;
2126
- }
2127
-
2128
- const someContext = this.generateDefaultContext();
2129
- let context = this.convertToContext(options, someContext);
2130
-
2131
- if (context.raw)
2132
- {
2133
- ____AnaLogger.Console.log(...args);
2134
- return;
2135
- }
2136
-
2137
- this.processOutput.apply(this, [context, ...args]);
2138
- }
2139
-
2140
- error(options, ...args)
2141
- {
2142
- if (this.options.hideError)
2143
- {
2144
- return;
2145
- }
2146
-
2147
- options = this.extractContextFromInput(options);
2148
-
2149
- // If the first parameter is not of context format,
2150
- // We use the error context and display
2151
- if (!this.isExtendedOptionsPassed(options))
2152
- {
2153
- const defaultContext = this.generateErrorContext();
2154
- this.processOutput.apply(this, [defaultContext, options, ...args]);
2155
- return;
2156
- }
2157
-
2158
- const errorContext = this.generateErrorContext();
2159
- let context = this.convertToContext(options, errorContext);
2160
-
2161
- let args0 = Array.prototype.slice.call(arguments, 1);
2162
- this.log(context, ...args0);
2163
- }
2164
-
2165
- overrideError()
2166
- {
2167
- if (!this.options.hideHookMessage)
2168
- {
2169
- ____AnaLogger.Console.log("AnaLogger: Hook placed on console.error");
2170
- }
2171
- this.#overridenMap.error = true;
2172
- console.error = this.onDisplayError.bind(this);
2173
- }
2174
-
2175
- attachConsole()
2176
- {
2177
- try
2178
- {
2179
- console.rawLog = ____AnaLogger.Console.log;
2180
- console.raw = ____AnaLogger.Console.log;
2181
-
2182
- console.rawInfo = ____AnaLogger.Console.info;
2183
- console.rawWarn = ____AnaLogger.Console.warn;
2184
- console.rawError = ____AnaLogger.Console.error;
2185
-
2186
- console.logHistory = this.logHistory;
2187
-
2188
- console.logHistory = this.logHistory;
2189
- COMMON_METHODS.forEach((name) =>
2190
- {
2191
- console[name] = function (...args)
2192
- {
2193
- this[name](...args);
2194
- }.bind(this);
2195
- });
2196
-
2197
- return true;
2198
- }
2199
- catch (e)
2200
- {
2201
- console.error({lid: 4321}, e.message);
2202
- }
2203
-
2204
- return false;
2205
- }
2206
-
2207
- overrideConsole({log = true, info = true, warn = true, error = false} = {})
2208
- {
2209
- if (!this.options.hideHookMessage)
2210
- {
2211
- ____AnaLogger.Console.log("AnaLogger: Hook placed on console.log");
2212
- }
2213
-
2214
- [{log}, {info}, {warn},].forEach(function (methodObj)
2215
- {
2216
- const methodName = Object.keys(methodObj)[0];
2217
- if (methodObj[methodName])
2218
- {
2219
- this.#overridenMap[methodName] = true;
2220
- console[methodName] = this.onDisplayLog.bind(this);
2221
- }
2222
- }.bind(this));
2223
-
2224
- if (error)
2225
- {
2226
- this.overrideError();
2227
- }
2228
-
2229
- this.attachConsole();
2230
- }
2231
-
2232
- removeOverrideError()
2233
- {
2234
- console.error = ____AnaLogger.Console.error;
2235
- this.#overridenMap.error = false;
2236
- }
2237
-
2238
- removeOverride({log = true, info = true, warn = true, error = false} = {})
2239
- {
2240
- if (log)
2241
- {
2242
- console.log = ____AnaLogger.Console.log;
2243
- this.#overridenMap.log = false;
2244
- }
2245
-
2246
- if (info)
2247
- {
2248
- console.info = ____AnaLogger.Console.info;
2249
- this.#overridenMap.info = false;
2250
- }
2251
-
2252
- if (warn)
2253
- {
2254
- console.warn = ____AnaLogger.Console.warn;
2255
- this.#overridenMap.warn = false;
2256
- }
2257
-
2258
- if (error)
2259
- {
2260
- this.removeOverrideError();
2261
- }
2262
-
2263
- }
2264
-
2265
- info(...args)
2266
- {
2267
- return this.log(...args);
2268
- }
2269
-
2270
- warn(...args)
2271
- {
2272
- return this.log(...args);
2273
- }
2274
-
2275
- table(...args)
2276
- {
2277
- if (!this.#overridenMap.log)
2278
- {
2279
- ____AnaLogger.Console.table(...args);
2280
- return;
2281
- }
2282
-
2283
- const currentLog = console.log;
2284
- console.log = ____AnaLogger.Console.log;
2285
- ____AnaLogger.Console.table(...args);
2286
- console.log = currentLog;
2287
- }
2288
-
2289
-
2290
- async takeScreenshotWithImageCapture()
2291
- {
2292
- try {
2293
- if (!this.isBrowser())
2294
- {
2295
- return;
2296
- }
2297
-
2298
- // 1. Get user media (camera stream)
2299
- const stream = await navigator.mediaDevices.getUserMedia({video: true});
2300
-
2301
- // 2. Get the video track
2302
- const videoTrack = stream.getVideoTracks()[0];
2303
-
2304
- // 3. Create an ImageCapture object
2305
- const imageCapture = new ImageCapture(videoTrack);
2306
-
2307
- // 4. Take a photo (screenshot)
2308
- const blob = await imageCapture.takePhoto();
2309
-
2310
- // 5. Create an image URL from the blob
2311
- const imageUrl = URL.createObjectURL(blob);
2312
-
2313
- // 6. Display the screenshot (optional)
2314
- const img = document.createElement('img');
2315
- img.src = imageUrl;
2316
- document.body.appendChild(img);
2317
-
2318
- // 7. Cleanup: Stop the camera stream
2319
- videoTrack.stop();
2320
- stream.getTracks().forEach(track => track.stop()); // Stop all tracks.
2321
-
2322
- // 8. Handle the blob as needed (e.g., download, upload)
2323
- console.log('Screenshot taken:', blob);
2324
- return blob; // Return the blob so it can be handled elsewhere.
2325
-
2326
- } catch (error) {
2327
- console.error('Error taking screenshot:', error);
2328
- // Handle errors (e.g., no camera access, user denied permission)
2329
- if (error.name === 'NotAllowedError') {
2330
- alert("Camera permissions denied. Please allow camera access.");
2331
- } else if (error.name === 'NotFoundError') {
2332
- alert("No camera found.");
2333
- }
2334
- return null; // Return null on error.
2335
- }
2336
- }
2337
-
2338
- takeScreenshot(pluginOptions = {})
2339
- {
2340
- debugger;
2341
- if (!this.isBrowser())
2342
- {
2343
- return;
2344
- }
2345
-
2346
- if (!htmlToImage) {
2347
- console.error("htmlToImage is not defined. Please install it first.");
2348
- return;
2349
- }
2350
-
2351
- htmlToImage
2352
- .toPng(divSource, pluginOptions.options)
2353
- .then(function (imageData)
2354
- {
2355
- // ------------------------------------
2356
- // Phase 1: We have the screenshot
2357
- // ------------------------------------
2358
-
2359
- anaLogger.uploadDataToRemote(imageData, context, (serverResponse) =>
2360
- {
2361
- });
2362
- })
2363
- .catch(function (error)
2364
- {
2365
- console.error("Something went wrong:", error);
2366
- });
2367
- }
2368
-
2369
- alert(...args)
2370
- {
2371
- if (!this.isBrowser())
2372
- {
2373
- return this.log(...args);
2374
- }
2375
-
2376
- let message;
2377
- if (args && ((args[0] && args[0].hasOwnProperty("lid")) || this.isContextValid(args[0])))
2378
- {
2379
- const someContext = this.generateDefaultContext();
2380
- let context = this.convertToContext(args[0], someContext);
2381
-
2382
- message = context.lid + ": " + args.slice(1).join(" | ");
2383
- }
2384
- else
2385
- {
2386
- message = args.join(" | ");
2387
- }
2388
-
2389
- alert(message);
2390
- }
2391
-
2392
- assert(condition, expected = true, ...args)
2393
- {
2394
- let result;
2395
-
2396
- try
2397
- {
2398
- if (typeof condition === "function")
2399
- {
2400
- result = condition(...args);
2401
- if (result !== expected)
2402
- {
2403
- this.error("Asset failed");
2404
- return false;
2405
- }
2406
-
2407
- if (!this.options.hidePassingTests)
2408
- {
2409
- this.log("SUCCESS: Assert passed");
2410
- }
2411
- return true;
2412
- }
2413
-
2414
- if (condition !== expected)
2415
- {
2416
- this.error("Assert failed");
2417
- return false;
2418
- }
2419
-
2420
- if (!this.options.hidePassingTests)
2421
- {
2422
- this.log("SUCCESS: Assert passed");
2423
- }
2424
- return true;
2425
- }
2426
- catch (e)
2427
- {
2428
- this.error("Unexpected error in assert");
2429
- }
2430
-
2431
- return false;
2432
- }
2433
-
2434
- /**
2435
- * Set default targets, contexts and log levels
2436
- * @returns {boolean}
2437
- */
2438
- #initialiseDefault()
2439
- {
2440
- try
2441
- {
2442
- // Register default targets: ALL and USER
2443
- this.setTargets(DEFAULT_LOG_TARGETS);
2444
-
2445
- // Register default log levels
2446
- this.setLogLevels(DEFAULT_LOG_LEVELS);
2447
-
2448
- // Register default context
2449
- this.setContexts(DEFAULT_LOG_CONTEXTS);
2450
- }
2451
- catch (e)
2452
- {
2453
- console.error({lid: 4321}, e.message);
2454
- }
2455
-
2456
- return false;
2457
- }
2458
-
2459
- /**
2460
- * Set standard Analogger format
2461
- * @example
2462
- * // Output Example
2463
- * // [14:01:06] DEFAULT: (1060) ⚡ " ✔ My log ..."
2464
- * @param activeTarget
2465
- * @param override
2466
- * @returns {boolean}
2467
- */
2468
- applyAnalogFormatting({activeTarget = "", override = false} = {})
2469
- {
2470
- try
2471
- {
2472
- const lidLenMax = 6;
2473
-
2474
- const LOG_CONTEXTS = {
2475
- STANDARD: null,
2476
- TEST : {color: "#B18904", symbol: "diamonds"},
2477
- };
2478
-
2479
- this.setDefaultContext(LOG_CONTEXTS.DEFAULT);
2480
-
2481
- activeTarget && this.setActiveTarget(activeTarget);
2482
-
2483
- this.setOptions({silent: false, hideError: false, hideHookMessage: true, lidLenMax});
2484
- if (override)
2485
- {
2486
- this.overrideConsole();
2487
- this.overrideError();
2488
- }
2489
-
2490
- return true;
2491
- }
2492
- catch (e)
2493
- {
2494
- /* istanbul ignore next */
2495
- console.error({lid: 3249}, e.message);
2496
- }
2497
-
2498
- /* istanbul ignore next */
2499
- return false;
2500
- }
2501
-
2502
- applyPredefinedFormat(name = PREDEFINED_FORMATS.DEFAULT_FORMAT, {activeTarget = "", override = false} = {})
2503
- {
2504
- if (name === PREDEFINED_FORMATS.DEFAULT_FORMAT)
2505
- {
2506
- return this.applyAnalogFormatting({activeTarget, override});
2507
- }
2508
- }
2509
-
2510
- static generateInstance()
2511
- {
2512
- return new ____AnaLogger();
2513
- }
2514
-
2515
- /**
2516
- * Returns an AnaLogger instance
2517
- * @returns {null}
2518
- */
2519
- static getInstance(num = 0)
2520
- {
2521
- if (!____AnaLogger.instanceCount)
2522
- {
2523
- return null;
2524
- }
2525
- return ____AnaLogger.#instances[num];
2526
- }
2527
-
2528
- /**
2529
- * Returns first existing AnaLogger instance,
2530
- * otherwise create a new instance
2531
- * @returns {*|____AnaLogger}
2532
- */
2533
- static generateMainInstance()
2534
- {
2535
- const mainInstance = ____AnaLogger.getInstance();
2536
- if (!mainInstance)
2537
- {
2538
- return new ____AnaLogger();
2539
- }
2540
-
2541
- return mainInstance;
2542
- }
2543
-
2544
- /**
2545
- * Override console.log and console.error
2546
- */
2547
- static startLogger()
2548
- {
2549
- const active = ____AnaLogger.generateMainInstance();
2550
- active.applyPredefinedFormat(PREDEFINED_FORMATS.DEFAULT_FORMAT, {override: true});
2551
- }
2552
-
2553
- static stopLogger()
2554
- {
2555
- const active = ____AnaLogger.generateMainInstance();
2556
- active.removeOverride();
2557
- active.removeOverrideError();
2558
- }
2559
-
2560
- convertToUrl({
2561
- protocol = DEFAULT.protocol,
2562
- host = DEFAULT.host,
2563
- port = DEFAULT.port,
2564
- pathname = DEFAULT.pathname
2565
- } = {})
2566
- {
2567
- const url = new URL("http://localhost");
2568
- url.protocol = protocol;
2569
- url.host = host;
2570
- url.port = port;
2571
- if (pathname)
2572
- {
2573
- url.pathname = pathname;
2574
- }
2575
-
2576
- return url.toString();
2577
- }
2578
-
2579
- generateLogToRemoteUrl(logToRemoteUrl = null, {pathname = DEFAULT.pathname} = {})
2580
- {
2581
- if (typeof logToRemoteUrl === "string" || logToRemoteUrl instanceof String)
2582
- {
2583
- return logToRemoteUrl;
2584
- }
2585
-
2586
- if (!this.isBrowser())
2587
- {
2588
- return null;
2589
- }
2590
-
2591
- const protocol = this.options.protocol || window.location.protocol + "//";
2592
- const host = this.options.host || window.location.host || DEFAULT.host;
2593
- const port = this.options.port || DEFAULT.port;
2594
- pathname = this.options.pathname || pathname;
2595
-
2596
- return this.convertToUrl({protocol, host, port, pathname});
2597
- }
2598
-
2599
- /**
2600
- * Install a plugin against the active instance
2601
- * @param methodName
2602
- * @param callback
2603
- * @param pluginName
2604
- */
2605
- addPlugin(methodName, callback, pluginName = "")
2606
- {
2607
- pluginName = pluginName || methodName;
2608
- this[methodName] = callback;
2609
-
2610
- ____AnaLogger.pluginTable[pluginName] = {
2611
- type: PLUGIN_TYPE.LOCAL,
2612
- methodName,
2613
- callback
2614
- };
2615
- }
2616
-
2617
- /**
2618
- * Install a plugin against the class (an instantiation with new is needed)
2619
- * @param methodName
2620
- * @param callback
2621
- * @param pluginName
2622
- */
2623
- addGlobalPlugin(methodName, callback, pluginName)
2624
- {
2625
- ____AnaLogger[methodName] = callback;
2626
-
2627
- ____AnaLogger.pluginTable[pluginName] = {
2628
- type: PLUGIN_TYPE.GLOBAL,
2629
- methodName,
2630
- callback
2631
- };
2632
-
2633
- }
2634
-
2635
- getPluginList()
2636
- {
2637
- return Object.keys(____AnaLogger.pluginTable);
2638
- }
2639
-
2640
- /**
2641
- * At the moment, this method behaviour is equivalent to an eventual isPluginRegistered method
2642
- * @param name
2643
- * @returns {boolean}
2644
- */
2645
- validatePlugin(name)
2646
- {
2647
- if (____AnaLogger.pluginTable[name])
2648
- {
2649
- return true;
2650
- }
2651
-
2652
- console.warn(`The plugin ${name} is not registered`);
2653
- return false;
2654
- }
2655
-
2656
- }
2657
-
2658
- // Export the class as default export
2659
- const __AnaLogger = ____AnaLogger;
2660
- export default __AnaLogger;
2661
-
2662
- // Export an instance
2663
- export const anaLogger = ____AnaLogger.generateMainInstance();
2664
-
2665
- const ___anaLogger = anaLogger;
2666
-
2667
- // Export the class as named export
2668
- export const AnaLogger = ____AnaLogger;
2669
-
2670
- const _AnaLogger = AnaLogger;
2671
-
2672
-
2673
-
2674
-
2675
-