@ricdotnet/logger 0.0.11 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prettierrc.json +7 -0
- package/Logs/28-12-2023-debug.log +9 -0
- package/Logs/28-12-2023-error.log +3 -0
- package/Logs/28-12-2023-info.log +3 -0
- package/Logs/28-12-2023-warn.log +3 -0
- package/Tests/Logger.spec.ts +25 -33
- package/Tests/WriteToFile.spec.ts +43 -0
- package/dist/src/Logger.d.ts +10 -6
- package/dist/src/Logger.js +37 -37
- package/dist/src/Logger.js.map +1 -1
- package/dist/src/Queue.d.ts +11 -0
- package/dist/src/Queue.js +64 -0
- package/dist/src/Queue.js.map +1 -0
- package/dist/src/Types.d.ts +8 -1
- package/package.json +4 -2
- package/src/Logger.ts +52 -43
- package/src/Queue.ts +78 -0
- package/src/Types.ts +8 -0
- package/Logs/29-8-2022-error.log +0 -24
- package/Logs/29-8-2022-info.log +0 -27
- package/Logs/29-8-2022-warn.log +0 -33
- package/index.ts +0 -1
- package/tsconfig.json +0 -18
package/.prettierrc.json
ADDED
package/Tests/Logger.spec.ts
CHANGED
|
@@ -1,55 +1,47 @@
|
|
|
1
1
|
import { Logger } from '../src/Logger';
|
|
2
|
-
import { Constants } from '../src/Constants';
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
// };
|
|
10
|
-
|
|
11
|
-
const consoleSpy = {
|
|
12
|
-
info: jest.spyOn(console, 'log'),
|
|
13
|
-
warn: jest.spyOn(console, 'warn'),
|
|
14
|
-
error: jest.spyOn(console, 'error'),
|
|
3
|
+
const loggerSpy = {
|
|
4
|
+
debug: null,
|
|
5
|
+
info: null,
|
|
6
|
+
warn: null,
|
|
7
|
+
error: null,
|
|
15
8
|
};
|
|
16
9
|
|
|
17
10
|
describe('Logger test', () => {
|
|
18
|
-
|
|
19
|
-
|
|
11
|
+
beforeAll(() => {
|
|
12
|
+
new Logger();
|
|
20
13
|
|
|
21
|
-
|
|
22
|
-
|
|
14
|
+
loggerSpy.debug = jest.spyOn(Logger.get(), 'debug');
|
|
15
|
+
loggerSpy.info = jest.spyOn(Logger.get(), 'info');
|
|
16
|
+
loggerSpy.warn = jest.spyOn(Logger.get(), 'warn');
|
|
17
|
+
loggerSpy.error = jest.spyOn(Logger.get(), 'error');
|
|
18
|
+
});
|
|
23
19
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
warn: jest.spyOn(loggerInstance, 'warn'),
|
|
27
|
-
error: jest.spyOn(loggerInstance, 'error')
|
|
28
|
-
};
|
|
20
|
+
it('can log a debug', async () => {
|
|
21
|
+
await Logger.get().debug('hello world');
|
|
29
22
|
|
|
30
|
-
loggerSpy.
|
|
31
|
-
loggerSpy.
|
|
32
|
-
loggerSpy.error.mockClear();
|
|
23
|
+
expect(loggerSpy.debug).toHaveBeenCalledWith('hello world');
|
|
24
|
+
expect(loggerSpy.debug).toHaveBeenCalledTimes(1);
|
|
33
25
|
});
|
|
34
26
|
|
|
35
27
|
it('can log an info', async () => {
|
|
36
|
-
await
|
|
28
|
+
await Logger.get().info('hello world');
|
|
37
29
|
|
|
38
|
-
|
|
39
|
-
|
|
30
|
+
expect(loggerSpy.info).toHaveBeenCalledWith('hello world');
|
|
31
|
+
expect(loggerSpy.info).toHaveBeenCalledTimes(1);
|
|
40
32
|
});
|
|
41
33
|
|
|
42
|
-
it('can log a warning', () => {
|
|
43
|
-
|
|
34
|
+
it('can log a warning', async () => {
|
|
35
|
+
await Logger.get().warn('hello world');
|
|
44
36
|
|
|
45
37
|
expect(loggerSpy.warn).toHaveBeenCalledWith('hello world');
|
|
46
|
-
|
|
38
|
+
expect(loggerSpy.warn).toHaveBeenCalledTimes(1);
|
|
47
39
|
});
|
|
48
40
|
|
|
49
|
-
it('can log an error', () => {
|
|
50
|
-
|
|
41
|
+
it('can log an error', async () => {
|
|
42
|
+
await Logger.get().error('hello world');
|
|
51
43
|
|
|
52
44
|
expect(loggerSpy.error).toHaveBeenCalledWith('hello world');
|
|
53
|
-
expect(
|
|
45
|
+
expect(loggerSpy.error).toHaveBeenCalledTimes(1);
|
|
54
46
|
});
|
|
55
47
|
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as fs from 'fs/promises';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { Logger } from '../src/Logger';
|
|
4
|
+
import {Queue} from "../src/Queue";
|
|
5
|
+
|
|
6
|
+
const spy = {
|
|
7
|
+
writeToFile: null,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
describe('Write to file test', () => {
|
|
11
|
+
beforeAll(() => {
|
|
12
|
+
new Logger({
|
|
13
|
+
logToFile: true,
|
|
14
|
+
logToConsole: false,
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
spy.writeToFile = jest.spyOn(Queue.prototype as any, 'writeToFile');
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// afterAll(async () => {
|
|
21
|
+
// await fs.rm(path.join(process.cwd(), 'Logs'), { recursive: true });
|
|
22
|
+
// });
|
|
23
|
+
|
|
24
|
+
it('can write a debug log to file', async () => {
|
|
25
|
+
await Logger.get().debug('hello world');
|
|
26
|
+
expect(spy.writeToFile).toHaveBeenCalledTimes(1);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('can write an info log to file', async () => {
|
|
30
|
+
await Logger.get().info('hello world');
|
|
31
|
+
expect(spy.writeToFile).toHaveBeenCalledTimes(1);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('can write a warn log to file', async () => {
|
|
35
|
+
await Logger.get().warn('hello world');
|
|
36
|
+
expect(spy.writeToFile).toHaveBeenCalledTimes(1);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('can write an error log to file', async () => {
|
|
40
|
+
await Logger.get().error('hello world');
|
|
41
|
+
expect(spy.writeToFile).toHaveBeenCalledTimes(1);
|
|
42
|
+
});
|
|
43
|
+
});
|
package/dist/src/Logger.d.ts
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import { ILogger
|
|
1
|
+
import { ILogger } from './Types';
|
|
2
2
|
export declare class Logger {
|
|
3
3
|
private readonly logDir;
|
|
4
4
|
private readonly logToConsole;
|
|
5
|
+
private readonly logToFile;
|
|
6
|
+
private readonly level;
|
|
7
|
+
private static logger;
|
|
8
|
+
private readonly logQueue;
|
|
5
9
|
constructor(options?: ILogger);
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
static get(): Logger;
|
|
11
|
+
debug(message: string): Promise<void>;
|
|
12
|
+
info(message: string): Promise<void>;
|
|
13
|
+
warn(message: string): Promise<void>;
|
|
14
|
+
error(message: string): Promise<void>;
|
|
11
15
|
}
|
package/dist/src/Logger.js
CHANGED
|
@@ -1,63 +1,63 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Logger = void 0;
|
|
4
|
-
const fs = require("fs/promises");
|
|
5
|
-
const path = require("path");
|
|
6
4
|
const Constants_1 = require("./Constants");
|
|
5
|
+
const Queue_1 = require("./Queue");
|
|
7
6
|
class Logger {
|
|
8
7
|
logDir;
|
|
9
8
|
logToConsole;
|
|
9
|
+
logToFile;
|
|
10
|
+
level;
|
|
11
|
+
static logger = null;
|
|
12
|
+
logQueue;
|
|
10
13
|
constructor(options) {
|
|
11
|
-
|
|
14
|
+
console.log('Initiating a logger...');
|
|
15
|
+
if (Logger.logger) {
|
|
16
|
+
console.warn('The logger was already initiated.');
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
12
19
|
this.logToConsole = options?.logToConsole ?? true;
|
|
13
|
-
this.
|
|
20
|
+
this.logToFile = options?.logToFile ?? false;
|
|
21
|
+
this.level = options?.level ?? 'info';
|
|
22
|
+
Logger.logger = this;
|
|
23
|
+
if (this.logToFile) {
|
|
24
|
+
this.logQueue = new Queue_1.Queue(options);
|
|
25
|
+
}
|
|
26
|
+
console.log('Logger initiated.');
|
|
27
|
+
}
|
|
28
|
+
static get() {
|
|
29
|
+
return Logger.logger;
|
|
14
30
|
}
|
|
15
|
-
async
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
await this.info(`Logs folder generated. Logging to: ${this.logDir}`);
|
|
31
|
+
async debug(message) {
|
|
32
|
+
if (this.logToFile) {
|
|
33
|
+
this.logQueue.add(message, 'debug');
|
|
19
34
|
}
|
|
20
|
-
|
|
21
|
-
|
|
35
|
+
if (this.logToConsole && this.level === 'debug') {
|
|
36
|
+
console.debug(`${Constants_1.Constants.TEXT_CYAN}[DEBUG]:${Constants_1.Constants.RESET} ${message}`);
|
|
22
37
|
}
|
|
23
38
|
}
|
|
24
39
|
async info(message) {
|
|
25
|
-
|
|
40
|
+
if (this.logToFile) {
|
|
41
|
+
this.logQueue.add(message, 'info');
|
|
42
|
+
}
|
|
26
43
|
if (this.logToConsole) {
|
|
27
|
-
console.log(`${Constants_1.Constants.TEXT_BLUE}[INFO]:${Constants_1.Constants.RESET} ${
|
|
44
|
+
console.log(`${Constants_1.Constants.TEXT_BLUE}[INFO]:${Constants_1.Constants.RESET} ${message}`);
|
|
28
45
|
}
|
|
29
46
|
}
|
|
30
47
|
async warn(message) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
console.warn(`${Constants_1.Constants.TEXT_YELLOW}[WARN]:${Constants_1.Constants.RESET} ${JSON.stringify(message)}`);
|
|
48
|
+
if (this.logToFile) {
|
|
49
|
+
this.logQueue.add(message, 'warn');
|
|
34
50
|
}
|
|
35
|
-
}
|
|
36
|
-
async error(message) {
|
|
37
|
-
await this.writeToFile(JSON.stringify(message), 'error');
|
|
38
51
|
if (this.logToConsole) {
|
|
39
|
-
console.
|
|
52
|
+
console.warn(`${Constants_1.Constants.TEXT_YELLOW}[WARN]:${Constants_1.Constants.RESET} ${message}`);
|
|
40
53
|
}
|
|
41
54
|
}
|
|
42
|
-
async
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const YEAR = new Date().getFullYear();
|
|
46
|
-
const HOURS = new Date().getHours();
|
|
47
|
-
const MINUTES = new Date().getMinutes();
|
|
48
|
-
const FULL_DATE = [DAY, MONTH, YEAR].join('-');
|
|
49
|
-
const FULL_TIME = [HOURS, MINUTES].join(':');
|
|
50
|
-
let logFile;
|
|
51
|
-
try {
|
|
52
|
-
logFile = await fs.readFile(path.join(this.logDir, `${FULL_DATE}-${type}.log`));
|
|
53
|
-
}
|
|
54
|
-
catch (e) {
|
|
55
|
-
const data = 'Log Time: ' + FULL_TIME + '\n' + message + '\n\n';
|
|
56
|
-
await fs.writeFile(path.join(this.logDir, `${FULL_DATE}-${type}.log`), data);
|
|
55
|
+
async error(message) {
|
|
56
|
+
if (this.logToFile) {
|
|
57
|
+
this.logQueue.add(message, 'error');
|
|
57
58
|
}
|
|
58
|
-
if (
|
|
59
|
-
|
|
60
|
-
await fs.writeFile(path.join(this.logDir, `${FULL_DATE}-${type}.log`), data);
|
|
59
|
+
if (this.logToConsole) {
|
|
60
|
+
console.error(`${Constants_1.Constants.TEXT_RED}[ERROR]:${Constants_1.Constants.RESET} ${message}`);
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
}
|
package/dist/src/Logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Logger.js","sourceRoot":"./","sources":["src/Logger.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"Logger.js","sourceRoot":"./","sources":["src/Logger.ts"],"names":[],"mappings":";;;AACA,2CAAwC;AAExC,mCAAgC;AAEhC,MAAa,MAAM;IACA,MAAM,CAAS;IACf,YAAY,CAAU;IACtB,SAAS,CAAU;IACnB,KAAK,CAAW;IACzB,MAAM,CAAC,MAAM,GAAW,IAAI,CAAC;IAEpB,QAAQ,CAAQ;IAEjC,YAAY,OAAiB;QAC3B,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;QACtC,IAAI,MAAM,CAAC,MAAM,EAAE;YACjB,OAAO,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;YAClD,OAAO;SACR;QAED,IAAI,CAAC,YAAY,GAAG,OAAO,EAAE,YAAY,IAAI,IAAI,CAAC;QAClD,IAAI,CAAC,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,KAAK,CAAC;QAC7C,IAAI,CAAC,KAAK,GAAG,OAAO,EAAE,KAAK,IAAI,MAAM,CAAC;QAEtC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC;QAErB,IAAI,IAAI,CAAC,SAAS,EAAE;YAClB,IAAI,CAAC,QAAQ,GAAG,IAAI,aAAK,CAAC,OAAO,CAAC,CAAC;SACpC;QAED,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IACnC,CAAC;IAED,MAAM,CAAC,GAAG;QACR,OAAO,MAAM,CAAC,MAAM,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,OAAe;QACzB,IAAI,IAAI,CAAC,SAAS,EAAE;YAClB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;SACrC;QACD,IAAI,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,KAAK,KAAK,OAAO,EAAE;YAC/C,OAAO,CAAC,KAAK,CACX,GAAG,qBAAS,CAAC,SAAS,WAAW,qBAAS,CAAC,KAAK,IAAI,OAAO,EAAE,CAC9D,CAAC;SACH;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,OAAe;QACxB,IAAI,IAAI,CAAC,SAAS,EAAE;YAClB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;SACpC;QACD,IAAI,IAAI,CAAC,YAAY,EAAE;YACrB,OAAO,CAAC,GAAG,CAAC,GAAG,qBAAS,CAAC,SAAS,UAAU,qBAAS,CAAC,KAAK,IAAI,OAAO,EAAE,CAAC,CAAC;SAC3E;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,OAAe;QACxB,IAAI,IAAI,CAAC,SAAS,EAAE;YAClB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;SACpC;QACD,IAAI,IAAI,CAAC,YAAY,EAAE;YACrB,OAAO,CAAC,IAAI,CACV,GAAG,qBAAS,CAAC,WAAW,UAAU,qBAAS,CAAC,KAAK,IAAI,OAAO,EAAE,CAC/D,CAAC;SACH;IACH,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,OAAe;QACzB,IAAI,IAAI,CAAC,SAAS,EAAE;YAClB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;SACrC;QACD,IAAI,IAAI,CAAC,YAAY,EAAE;YACrB,OAAO,CAAC,KAAK,CACX,GAAG,qBAAS,CAAC,QAAQ,WAAW,qBAAS,CAAC,KAAK,IAAI,OAAO,EAAE,CAC7D,CAAC;SACH;IACH,CAAC;;AAzEH,wBA0EC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ILogger, LogLevel } from './Types';
|
|
2
|
+
export declare class Queue {
|
|
3
|
+
private logQueue;
|
|
4
|
+
private isRunning;
|
|
5
|
+
private readonly logDir;
|
|
6
|
+
constructor(options: ILogger);
|
|
7
|
+
private checkLogDir;
|
|
8
|
+
add(message: string, level: LogLevel): void;
|
|
9
|
+
runQueue(): Promise<void>;
|
|
10
|
+
private writeToFile;
|
|
11
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Queue = void 0;
|
|
4
|
+
const fs = require("fs/promises");
|
|
5
|
+
const path = require("path");
|
|
6
|
+
const Logger_1 = require("./Logger");
|
|
7
|
+
class Queue {
|
|
8
|
+
logQueue;
|
|
9
|
+
isRunning;
|
|
10
|
+
logDir;
|
|
11
|
+
constructor(options) {
|
|
12
|
+
this.logQueue = [];
|
|
13
|
+
this.isRunning = false;
|
|
14
|
+
this.logDir = options?.directory ?? 'Logs';
|
|
15
|
+
this.checkLogDir();
|
|
16
|
+
}
|
|
17
|
+
async checkLogDir() {
|
|
18
|
+
try {
|
|
19
|
+
await fs.mkdir(this.logDir);
|
|
20
|
+
await Logger_1.Logger.get().debug(`Logs folder generated. Logging to: ${this.logDir}`);
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
await Logger_1.Logger.get().debug(`Logs folder already exists. Logging to: ${this.logDir}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
add(message, level) {
|
|
27
|
+
this.logQueue.push({ message, level });
|
|
28
|
+
if (!this.isRunning) {
|
|
29
|
+
this.isRunning = true;
|
|
30
|
+
this.runQueue();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async runQueue() {
|
|
34
|
+
const { message, level } = this.logQueue.shift();
|
|
35
|
+
await this.writeToFile(message, level);
|
|
36
|
+
if (this.logQueue.length) {
|
|
37
|
+
return this.runQueue();
|
|
38
|
+
}
|
|
39
|
+
this.isRunning = false;
|
|
40
|
+
}
|
|
41
|
+
async writeToFile(message, level) {
|
|
42
|
+
const DAY = new Date().getDate();
|
|
43
|
+
const MONTH = new Date().getMonth() + 1;
|
|
44
|
+
const YEAR = new Date().getFullYear();
|
|
45
|
+
const HOURS = new Date().getHours();
|
|
46
|
+
const MINUTES = new Date().getMinutes();
|
|
47
|
+
const FULL_DATE = [DAY, MONTH, YEAR].join('-');
|
|
48
|
+
const FULL_TIME = [HOURS, MINUTES].join(':');
|
|
49
|
+
let logFile;
|
|
50
|
+
try {
|
|
51
|
+
logFile = await fs.readFile(path.join(this.logDir, `${FULL_DATE}-${level}.log`));
|
|
52
|
+
}
|
|
53
|
+
catch (e) {
|
|
54
|
+
const data = 'Log Time: ' + FULL_TIME + '\n' + message + '\n\n';
|
|
55
|
+
await fs.writeFile(path.join(this.logDir, `${FULL_DATE}-${level}.log`), data);
|
|
56
|
+
}
|
|
57
|
+
if (logFile) {
|
|
58
|
+
const data = logFile + 'Log Time: ' + FULL_TIME + '\n' + message + '\n\n';
|
|
59
|
+
await fs.writeFile(path.join(this.logDir, `${FULL_DATE}-${level}.log`), data);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
exports.Queue = Queue;
|
|
64
|
+
//# sourceMappingURL=Queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Queue.js","sourceRoot":"./","sources":["src/Queue.ts"],"names":[],"mappings":"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"}
|
package/dist/src/Types.d.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
|
-
export
|
|
1
|
+
export type Primitives = string | number | object;
|
|
2
|
+
export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
3
|
+
export type LogObject = {
|
|
4
|
+
message: string;
|
|
5
|
+
level: LogLevel;
|
|
6
|
+
};
|
|
2
7
|
export interface ILogger {
|
|
3
8
|
directory?: string;
|
|
4
9
|
logToConsole?: boolean;
|
|
10
|
+
logToFile?: boolean;
|
|
11
|
+
level?: LogLevel;
|
|
5
12
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ricdotnet/logger",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "A logger utility for my personal projects.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -25,8 +25,10 @@
|
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"@types/jest": "^27.4.1",
|
|
27
27
|
"jest": "^27.5.1",
|
|
28
|
+
"prettier": "3.1.1",
|
|
28
29
|
"ts-jest": "^27.1.4",
|
|
29
30
|
"ts-node": "^10.7.0",
|
|
30
31
|
"typescript": "^4.6.3"
|
|
31
|
-
}
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {}
|
|
32
34
|
}
|
package/src/Logger.ts
CHANGED
|
@@ -1,71 +1,80 @@
|
|
|
1
1
|
import * as fs from 'fs/promises';
|
|
2
|
-
import * as path from 'path';
|
|
3
2
|
import { Constants } from './Constants';
|
|
4
|
-
import { ILogger,
|
|
3
|
+
import { ILogger, LogLevel } from './Types';
|
|
4
|
+
import { Queue } from './Queue';
|
|
5
5
|
|
|
6
6
|
export class Logger {
|
|
7
|
-
|
|
8
7
|
private readonly logDir: string;
|
|
9
8
|
private readonly logToConsole: boolean;
|
|
9
|
+
private readonly logToFile: boolean;
|
|
10
|
+
private readonly level: LogLevel;
|
|
11
|
+
private static logger: Logger = null;
|
|
12
|
+
|
|
13
|
+
private readonly logQueue: Queue;
|
|
10
14
|
|
|
11
15
|
constructor(options?: ILogger) {
|
|
12
|
-
|
|
16
|
+
console.log('Initiating a logger...');
|
|
17
|
+
if (Logger.logger) {
|
|
18
|
+
console.warn('The logger was already initiated.');
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
13
22
|
this.logToConsole = options?.logToConsole ?? true;
|
|
14
|
-
this.
|
|
15
|
-
|
|
23
|
+
this.logToFile = options?.logToFile ?? false;
|
|
24
|
+
this.level = options?.level ?? 'info';
|
|
16
25
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
} catch (error) {
|
|
22
|
-
await this.info(`Logs folder already exists. Logging to: ${this.logDir}`);
|
|
26
|
+
Logger.logger = this;
|
|
27
|
+
|
|
28
|
+
if (this.logToFile) {
|
|
29
|
+
this.logQueue = new Queue(options);
|
|
23
30
|
}
|
|
31
|
+
|
|
32
|
+
console.log('Logger initiated.');
|
|
24
33
|
}
|
|
25
34
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
35
|
+
static get(): Logger {
|
|
36
|
+
return Logger.logger;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async debug(message: string) {
|
|
40
|
+
if (this.logToFile) {
|
|
41
|
+
this.logQueue.add(message, 'debug');
|
|
42
|
+
}
|
|
43
|
+
if (this.logToConsole && this.level === 'debug') {
|
|
44
|
+
console.debug(
|
|
45
|
+
`${Constants.TEXT_CYAN}[DEBUG]:${Constants.RESET} ${message}`,
|
|
46
|
+
);
|
|
30
47
|
}
|
|
31
48
|
}
|
|
32
49
|
|
|
33
|
-
async
|
|
34
|
-
|
|
50
|
+
async info(message: string) {
|
|
51
|
+
if (this.logToFile) {
|
|
52
|
+
this.logQueue.add(message, 'info');
|
|
53
|
+
}
|
|
35
54
|
if (this.logToConsole) {
|
|
36
|
-
console.
|
|
55
|
+
console.log(`${Constants.TEXT_BLUE}[INFO]:${Constants.RESET} ${message}`);
|
|
37
56
|
}
|
|
38
57
|
}
|
|
39
58
|
|
|
40
|
-
async
|
|
41
|
-
|
|
59
|
+
async warn(message: string) {
|
|
60
|
+
if (this.logToFile) {
|
|
61
|
+
this.logQueue.add(message, 'warn');
|
|
62
|
+
}
|
|
42
63
|
if (this.logToConsole) {
|
|
43
|
-
console.
|
|
64
|
+
console.warn(
|
|
65
|
+
`${Constants.TEXT_YELLOW}[WARN]:${Constants.RESET} ${message}`,
|
|
66
|
+
);
|
|
44
67
|
}
|
|
45
68
|
}
|
|
46
69
|
|
|
47
|
-
async
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const YEAR: number = new Date().getFullYear();
|
|
51
|
-
const HOURS: number = new Date().getHours();
|
|
52
|
-
const MINUTES: number = new Date().getMinutes();
|
|
53
|
-
|
|
54
|
-
const FULL_DATE: string = [DAY, MONTH, YEAR].join('-');
|
|
55
|
-
const FULL_TIME: string = [HOURS, MINUTES].join(':');
|
|
56
|
-
|
|
57
|
-
let logFile;
|
|
58
|
-
try {
|
|
59
|
-
logFile = await fs.readFile(path.join(this.logDir, `${FULL_DATE}-${type}.log`));
|
|
60
|
-
} catch (e) {
|
|
61
|
-
const data = 'Log Time: ' + FULL_TIME + '\n' + message + '\n\n';
|
|
62
|
-
await fs.writeFile(path.join(this.logDir, `${FULL_DATE}-${type}.log`), data);
|
|
70
|
+
async error(message: string) {
|
|
71
|
+
if (this.logToFile) {
|
|
72
|
+
this.logQueue.add(message, 'error');
|
|
63
73
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
74
|
+
if (this.logToConsole) {
|
|
75
|
+
console.error(
|
|
76
|
+
`${Constants.TEXT_RED}[ERROR]:${Constants.RESET} ${message}`,
|
|
77
|
+
);
|
|
68
78
|
}
|
|
69
79
|
}
|
|
70
|
-
|
|
71
80
|
}
|
package/src/Queue.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import * as fs from 'fs/promises';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { ILogger, LogLevel, LogObject } from './Types';
|
|
4
|
+
import {Logger} from "./Logger";
|
|
5
|
+
|
|
6
|
+
export class Queue {
|
|
7
|
+
private logQueue: LogObject[];
|
|
8
|
+
private isRunning: boolean;
|
|
9
|
+
private readonly logDir: string;
|
|
10
|
+
|
|
11
|
+
constructor(options: ILogger) {
|
|
12
|
+
this.logQueue = [];
|
|
13
|
+
this.isRunning = false;
|
|
14
|
+
this.logDir = options?.directory ?? 'Logs';
|
|
15
|
+
this.checkLogDir();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// TODO: update this maybe
|
|
19
|
+
private async checkLogDir() {
|
|
20
|
+
try {
|
|
21
|
+
await fs.mkdir(this.logDir);
|
|
22
|
+
await Logger.get().debug(`Logs folder generated. Logging to: ${this.logDir}`);
|
|
23
|
+
} catch (error) {
|
|
24
|
+
await Logger.get().debug(`Logs folder already exists. Logging to: ${this.logDir}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
add(message: string, level: LogLevel) {
|
|
30
|
+
this.logQueue.push({ message, level });
|
|
31
|
+
if (!this.isRunning) {
|
|
32
|
+
this.isRunning = true;
|
|
33
|
+
this.runQueue();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async runQueue(): Promise<void> {
|
|
38
|
+
const { message, level } = this.logQueue.shift();
|
|
39
|
+
await this.writeToFile(message, level);
|
|
40
|
+
if (this.logQueue.length) {
|
|
41
|
+
return this.runQueue();
|
|
42
|
+
}
|
|
43
|
+
this.isRunning = false;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// TODO: rewrite better...
|
|
47
|
+
private async writeToFile(message: string, level: LogLevel) {
|
|
48
|
+
const DAY: number = new Date().getDate();
|
|
49
|
+
const MONTH: number = new Date().getMonth() + 1; // +1 because it goes 0-11
|
|
50
|
+
const YEAR: number = new Date().getFullYear();
|
|
51
|
+
const HOURS: number = new Date().getHours();
|
|
52
|
+
const MINUTES: number = new Date().getMinutes();
|
|
53
|
+
|
|
54
|
+
const FULL_DATE: string = [DAY, MONTH, YEAR].join('-');
|
|
55
|
+
const FULL_TIME: string = [HOURS, MINUTES].join(':');
|
|
56
|
+
|
|
57
|
+
let logFile: string | Buffer;
|
|
58
|
+
try {
|
|
59
|
+
logFile = await fs.readFile(
|
|
60
|
+
path.join(this.logDir, `${FULL_DATE}-${level}.log`),
|
|
61
|
+
);
|
|
62
|
+
} catch (e) {
|
|
63
|
+
const data = 'Log Time: ' + FULL_TIME + '\n' + message + '\n\n';
|
|
64
|
+
await fs.writeFile(
|
|
65
|
+
path.join(this.logDir, `${FULL_DATE}-${level}.log`),
|
|
66
|
+
data,
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (logFile) {
|
|
71
|
+
const data = logFile + 'Log Time: ' + FULL_TIME + '\n' + message + '\n\n';
|
|
72
|
+
await fs.writeFile(
|
|
73
|
+
path.join(this.logDir, `${FULL_DATE}-${level}.log`),
|
|
74
|
+
data,
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
package/src/Types.ts
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
export type Primitives = string | number | object;
|
|
2
|
+
export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
3
|
+
|
|
4
|
+
export type LogObject = {
|
|
5
|
+
message: string;
|
|
6
|
+
level: LogLevel;
|
|
7
|
+
};
|
|
2
8
|
|
|
3
9
|
export interface ILogger {
|
|
4
10
|
directory?: string;
|
|
5
11
|
logToConsole?: boolean;
|
|
12
|
+
logToFile?: boolean;
|
|
13
|
+
level?: LogLevel;
|
|
6
14
|
}
|
package/Logs/29-8-2022-error.log
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
Log Time: 11:13
|
|
2
|
-
hello world
|
|
3
|
-
|
|
4
|
-
Log Time: 11:13
|
|
5
|
-
hello world
|
|
6
|
-
|
|
7
|
-
Log Time: 11:14
|
|
8
|
-
hello world
|
|
9
|
-
|
|
10
|
-
Log Time: 11:15
|
|
11
|
-
hello world
|
|
12
|
-
|
|
13
|
-
Log Time: 11:18
|
|
14
|
-
hello world
|
|
15
|
-
|
|
16
|
-
Log Time: 11:19
|
|
17
|
-
hello world
|
|
18
|
-
|
|
19
|
-
Log Time: 11:19
|
|
20
|
-
hello world
|
|
21
|
-
|
|
22
|
-
Log Time: 11:20
|
|
23
|
-
hello world
|
|
24
|
-
|
package/Logs/29-8-2022-info.log
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
Log Time: 11:13
|
|
2
|
-
hello world
|
|
3
|
-
|
|
4
|
-
Log Time: 11:13
|
|
5
|
-
Logs folder generated.
|
|
6
|
-
|
|
7
|
-
Log Time: 11:13
|
|
8
|
-
hello world
|
|
9
|
-
|
|
10
|
-
Log Time: 11:14
|
|
11
|
-
hello world
|
|
12
|
-
|
|
13
|
-
Log Time: 11:15
|
|
14
|
-
hello world
|
|
15
|
-
|
|
16
|
-
Log Time: 11:18
|
|
17
|
-
hello world
|
|
18
|
-
|
|
19
|
-
Log Time: 11:19
|
|
20
|
-
hello world
|
|
21
|
-
|
|
22
|
-
Log Time: 11:19
|
|
23
|
-
hello world
|
|
24
|
-
|
|
25
|
-
Log Time: 11:20
|
|
26
|
-
hello world
|
|
27
|
-
|
package/Logs/29-8-2022-warn.log
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
Log Time: 11:13
|
|
2
|
-
hello world
|
|
3
|
-
|
|
4
|
-
Log Time: 11:13
|
|
5
|
-
hello world
|
|
6
|
-
|
|
7
|
-
Log Time: 11:14
|
|
8
|
-
hello world
|
|
9
|
-
|
|
10
|
-
Log Time: 11:15
|
|
11
|
-
hello world
|
|
12
|
-
|
|
13
|
-
Log Time: 11:17
|
|
14
|
-
hello world
|
|
15
|
-
|
|
16
|
-
Log Time: 11:17
|
|
17
|
-
hello world
|
|
18
|
-
|
|
19
|
-
Log Time: 11:17
|
|
20
|
-
hello world
|
|
21
|
-
|
|
22
|
-
Log Time: 11:18
|
|
23
|
-
hello world
|
|
24
|
-
|
|
25
|
-
Log Time: 11:19
|
|
26
|
-
hello world
|
|
27
|
-
|
|
28
|
-
Log Time: 11:19
|
|
29
|
-
hello world
|
|
30
|
-
|
|
31
|
-
Log Time: 11:20
|
|
32
|
-
hello world
|
|
33
|
-
|
package/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { Logger } from './src/Logger';
|
package/tsconfig.json
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"module": "commonjs",
|
|
4
|
-
"target": "esnext",
|
|
5
|
-
"sourceMap": true,
|
|
6
|
-
"removeComments": true,
|
|
7
|
-
"outDir": "dist",
|
|
8
|
-
"sourceRoot": "./",
|
|
9
|
-
"allowJs": true,
|
|
10
|
-
"declaration": true,
|
|
11
|
-
"resolveJsonModule": true
|
|
12
|
-
},
|
|
13
|
-
"exclude": [
|
|
14
|
-
"node_modules",
|
|
15
|
-
"Tests",
|
|
16
|
-
"jest.config.js",
|
|
17
|
-
]
|
|
18
|
-
}
|