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