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