@warlock.js/logger 1.0.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.
Files changed (66) hide show
  1. package/README.md +381 -0
  2. package/cjs/LogChannel.d.ts +20 -0
  3. package/cjs/LogChannel.d.ts.map +1 -0
  4. package/cjs/LogChannel.js +14 -0
  5. package/cjs/LogChannel.js.map +1 -0
  6. package/cjs/channels/console-log.d.ts +17 -0
  7. package/cjs/channels/console-log.d.ts.map +1 -0
  8. package/cjs/channels/console-log.js +44 -0
  9. package/cjs/channels/console-log.js.map +1 -0
  10. package/cjs/channels/file-log.d.ts +202 -0
  11. package/cjs/channels/file-log.d.ts.map +1 -0
  12. package/cjs/channels/file-log.js +315 -0
  13. package/cjs/channels/file-log.js.map +1 -0
  14. package/cjs/channels/index.d.ts +4 -0
  15. package/cjs/channels/index.d.ts.map +1 -0
  16. package/cjs/channels/json-file-log.d.ts +25 -0
  17. package/cjs/channels/json-file-log.d.ts.map +1 -0
  18. package/cjs/channels/json-file-log.js +73 -0
  19. package/cjs/channels/json-file-log.js.map +1 -0
  20. package/cjs/index.d.ts +8 -0
  21. package/cjs/index.d.ts.map +1 -0
  22. package/cjs/index.js +1 -0
  23. package/cjs/index.js.map +1 -0
  24. package/cjs/logger.d.ts +74 -0
  25. package/cjs/logger.d.ts.map +1 -0
  26. package/cjs/logger.js +84 -0
  27. package/cjs/logger.js.map +1 -0
  28. package/cjs/types.d.ts +21 -0
  29. package/cjs/types.d.ts.map +1 -0
  30. package/cjs/utils.d.ts +6 -0
  31. package/cjs/utils.d.ts.map +1 -0
  32. package/cjs/utils.js +21 -0
  33. package/cjs/utils.js.map +1 -0
  34. package/esm/LogChannel.d.ts +20 -0
  35. package/esm/LogChannel.d.ts.map +1 -0
  36. package/esm/LogChannel.js +14 -0
  37. package/esm/LogChannel.js.map +1 -0
  38. package/esm/channels/console-log.d.ts +17 -0
  39. package/esm/channels/console-log.d.ts.map +1 -0
  40. package/esm/channels/console-log.js +44 -0
  41. package/esm/channels/console-log.js.map +1 -0
  42. package/esm/channels/file-log.d.ts +202 -0
  43. package/esm/channels/file-log.d.ts.map +1 -0
  44. package/esm/channels/file-log.js +315 -0
  45. package/esm/channels/file-log.js.map +1 -0
  46. package/esm/channels/index.d.ts +4 -0
  47. package/esm/channels/index.d.ts.map +1 -0
  48. package/esm/channels/json-file-log.d.ts +25 -0
  49. package/esm/channels/json-file-log.d.ts.map +1 -0
  50. package/esm/channels/json-file-log.js +73 -0
  51. package/esm/channels/json-file-log.js.map +1 -0
  52. package/esm/index.d.ts +8 -0
  53. package/esm/index.d.ts.map +1 -0
  54. package/esm/index.js +1 -0
  55. package/esm/index.js.map +1 -0
  56. package/esm/logger.d.ts +74 -0
  57. package/esm/logger.d.ts.map +1 -0
  58. package/esm/logger.js +84 -0
  59. package/esm/logger.js.map +1 -0
  60. package/esm/types.d.ts +21 -0
  61. package/esm/types.d.ts.map +1 -0
  62. package/esm/utils.d.ts +6 -0
  63. package/esm/utils.d.ts.map +1 -0
  64. package/esm/utils.js +21 -0
  65. package/esm/utils.js.map +1 -0
  66. package/package.json +39 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;AAEvE,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAElE,MAAM,WAAW,WAAW;IAC1B;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,GAAG,CACD,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,GAAG,EACZ,KAAK,EAAE,QAAQ,GACd,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB"}
package/cjs/utils.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ export declare function captureAnyUnhandledRejection(): void;
2
+ /**
3
+ * Clear message from any terminal codes
4
+ */
5
+ export declare function clearMessage(message: any): any;
6
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAEA,wBAAgB,4BAA4B,SAY3C;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,GAAG,OAKxC"}
package/cjs/utils.js ADDED
@@ -0,0 +1,21 @@
1
+ 'use strict';var logger=require('./logger.js');function captureAnyUnhandledRejection() {
2
+ process.on("unhandledRejection", (reason, promise) => {
3
+ logger.log.error("app", reason, promise);
4
+ console.log(promise);
5
+ // console.trace();
6
+ });
7
+ process.on("uncaughtException", (error) => {
8
+ logger.log.error("app", "error", error);
9
+ // console.trace();
10
+ console.log(error);
11
+ });
12
+ }
13
+ /**
14
+ * Clear message from any terminal codes
15
+ */
16
+ function clearMessage(message) {
17
+ if (typeof message !== "string")
18
+ return message;
19
+ // eslint-disable-next-line no-control-regex
20
+ return message.replace(/\u001b[^m]*?m/g, "");
21
+ }exports.captureAnyUnhandledRejection=captureAnyUnhandledRejection;exports.clearMessage=clearMessage;//# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sources":["../src/utils.ts"],"sourcesContent":[null],"names":["log"],"mappings":"wDAEgB,4BAA4B,GAAA;IAC1C,OAAO,CAAC,EAAE,CAAC,oBAAoB,EAAE,CAAC,MAAc,EAAE,OAAO,KAAI;QAC3DA,UAAG,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AAClC,QAAA,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;;AAEvB,KAAC,CAAC,CAAC;IAEH,OAAO,CAAC,EAAE,CAAC,mBAAmB,EAAE,CAAC,KAAK,KAAI;QACxCA,UAAG,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;;AAEjC,QAAA,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AACrB,KAAC,CAAC,CAAC;AACL,CAAC;AAED;;AAEG;AACG,SAAU,YAAY,CAAC,OAAY,EAAA;IACvC,IAAI,OAAO,OAAO,KAAK,QAAQ;AAAE,QAAA,OAAO,OAAO,CAAC;;IAGhD,OAAO,OAAO,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC;AAC/C"}
@@ -0,0 +1,20 @@
1
+ import { LogContract, LogLevel } from "./types";
2
+ export declare abstract class LogChannel implements LogContract {
3
+ /**
4
+ * Channel name
5
+ */
6
+ name: string;
7
+ /**
8
+ * Channel description
9
+ */
10
+ description?: string;
11
+ /**
12
+ * Determine if channel is logging in terminal
13
+ */
14
+ terminal: boolean;
15
+ /**
16
+ * Log the given message
17
+ */
18
+ abstract log(module: string, action: string, message: any, level: LogLevel): void | Promise<void>;
19
+ }
20
+ //# sourceMappingURL=LogChannel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LogChannel.d.ts","sourceRoot":"","sources":["../src/LogChannel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEhD,8BAAsB,UAAW,YAAW,WAAW;IACrD;;OAEG;IACI,IAAI,EAAG,MAAM,CAAC;IAErB;;OAEG;IACI,WAAW,CAAC,EAAE,MAAM,CAAC;IAE5B;;OAEG;IACI,QAAQ,UAAS;IAExB;;OAEG;aACa,GAAG,CACjB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,GAAG,EACZ,KAAK,EAAE,QAAQ,GACd,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;CACxB"}
@@ -0,0 +1,14 @@
1
+ class LogChannel {
2
+ /**
3
+ * Channel name
4
+ */
5
+ name;
6
+ /**
7
+ * Channel description
8
+ */
9
+ description;
10
+ /**
11
+ * Determine if channel is logging in terminal
12
+ */
13
+ terminal = false;
14
+ }export{LogChannel};//# sourceMappingURL=LogChannel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LogChannel.js","sources":["../src/LogChannel.ts"],"sourcesContent":[null],"names":[],"mappings":"MAEsB,UAAU,CAAA;AAC9B;;AAEG;AACI,IAAA,IAAI,CAAU;AAErB;;AAEG;AACI,IAAA,WAAW,CAAU;AAE5B;;AAEG;IACI,QAAQ,GAAG,KAAK,CAAC;AAWzB"}
@@ -0,0 +1,17 @@
1
+ import { LogChannel } from "../LogChannel";
2
+ import { LogLevel } from "../types";
3
+ export declare class ConsoleLog extends LogChannel {
4
+ /**
5
+ * {@inheritdoc}
6
+ */
7
+ name: string;
8
+ /**
9
+ * Determine if channel is logging in terminal
10
+ */
11
+ terminal: boolean;
12
+ /**
13
+ * {@inheritdoc}
14
+ */
15
+ log(module: string, action: string, message: any, level: LogLevel): void;
16
+ }
17
+ //# sourceMappingURL=console-log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console-log.d.ts","sourceRoot":"","sources":["../../src/channels/console-log.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC,qBAAa,UAAW,SAAQ,UAAU;IACxC;;OAEG;IACI,IAAI,SAAa;IAExB;;OAEG;IACI,QAAQ,UAAQ;IAEvB;;OAEG;IACI,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ;CAsEzE"}
@@ -0,0 +1,44 @@
1
+ import {colors}from'@mongez/copper';import {LogChannel}from'../LogChannel.js';class ConsoleLog extends LogChannel {
2
+ /**
3
+ * {@inheritdoc}
4
+ */
5
+ name = "console";
6
+ /**
7
+ * Determine if channel is logging in terminal
8
+ */
9
+ terminal = true;
10
+ /**
11
+ * {@inheritdoc}
12
+ */
13
+ log(module, action, message, level) {
14
+ // display date and time with milliseconds
15
+ const date = new Date().toISOString(); // i.e 2021-01-01T00:00:00.000Z
16
+ switch (level) {
17
+ case "debug":
18
+ // add a debug icon
19
+ console.log(colors.magentaBright("⚙"), colors.yellow(`(${date})`), colors.cyan(`[${module}]`), colors.magenta(`[${action}]`), colors.magentaBright(message));
20
+ break;
21
+ case "info":
22
+ // add an info icon
23
+ console.log(colors.blueBright("ℹ"), colors.yellow(`(${date})`), colors.cyan(`[${module}]`), colors.magenta(`[${action}]`), colors.blueBright(message));
24
+ break;
25
+ case "warn":
26
+ // add a warning icon
27
+ console.log(colors.yellow("⚠"), colors.green(`(${date})`), colors.cyan(`[${module}]`), colors.magenta(`[${action}]`), colors.yellowBright(message));
28
+ break;
29
+ case "error":
30
+ // add an error icon
31
+ console.log(colors.red("✗"), colors.yellow(`(${date})`), colors.cyan(`[${module}]`), colors.magenta(`[${action}]`), colors.redBright(message));
32
+ break;
33
+ case "success":
34
+ // add a success icon
35
+ console.log(colors.green("✓"), colors.yellow(`(${date})`), colors.cyan(`[${module}]`), colors.magenta(`[${action}]`), colors.greenBright(message));
36
+ break;
37
+ default:
38
+ console.log("[log]", colors.yellow(`(${date})`), colors.cyan(`[${module}]`), colors.magenta(`[${action}]`), message);
39
+ }
40
+ if (typeof message === "object") {
41
+ console.log(message);
42
+ }
43
+ }
44
+ }export{ConsoleLog};//# sourceMappingURL=console-log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console-log.js","sources":["../../src/channels/console-log.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -0,0 +1,202 @@
1
+ import { LogChannel } from "../LogChannel";
2
+ import { LogContract, LogLevel } from "../types";
3
+ export type FilteringOptions = {
4
+ level: LogLevel;
5
+ module: string;
6
+ action: string;
7
+ };
8
+ export type FileLogConfig = {
9
+ storagePath?: string;
10
+ /**
11
+ * File name, without extension
12
+ */
13
+ name?: string;
14
+ /**
15
+ * chunk mode
16
+ * If set to `single`, the logs will be created in a single file, unless the rotate is set to true
17
+ * If set to `daily`, the logs will be created in a daily file, unless the rotate is set to true
18
+ * If set to `hourly`, the logs will be created in an hourly file, unless the rotate is set to true
19
+ * @default single
20
+ */
21
+ chunk?: "single" | "daily" | "hourly";
22
+ /**
23
+ * Whether to rotate the file
24
+ *
25
+ * @default true
26
+ */
27
+ rotate?: boolean;
28
+ /**
29
+ * File Extension
30
+ *
31
+ * @default log
32
+ */
33
+ extension?: string;
34
+ /**
35
+ * If rotate is set, the rotate name will be added to the file name suffixed with `-`
36
+ *
37
+ * @default DD-MM-YYYY
38
+ */
39
+ rotateFileName?: string;
40
+ /**
41
+ * Max file size before rotating the file
42
+ *
43
+ * @default 10MB
44
+ */
45
+ maxFileSize?: number;
46
+ /**
47
+ * Set the max messages that needs to be added before writing to the file
48
+ *
49
+ * @default 100
50
+ */
51
+ maxMessagesToWrite?: number;
52
+ /**
53
+ * Group logs by
54
+ * Please note that the order matters here
55
+ * For example, if you set `groupBy: ['level', 'module']`, the logs will be added in level name first, then by module
56
+ *
57
+ * @default none
58
+ */
59
+ groupBy?: ("level" | "module" | "action")[];
60
+ /**
61
+ * Define what levels should be logged
62
+ *
63
+ * @default all
64
+ */
65
+ levels?: LogLevel[];
66
+ /**
67
+ * Filter what logs should be logged
68
+ *
69
+ * @default all
70
+ */
71
+ filter?: (options: FilteringOptions) => boolean;
72
+ /**
73
+ * Date and time format
74
+ */
75
+ dateFormat?: {
76
+ date?: string;
77
+ time?: string;
78
+ };
79
+ };
80
+ export type LogMessage = {
81
+ content: string;
82
+ level: LogLevel;
83
+ date: string;
84
+ module: string;
85
+ action: string;
86
+ stack: string;
87
+ };
88
+ export declare class FileLog extends LogChannel implements LogContract {
89
+ /**
90
+ * {@inheritdoc}
91
+ */
92
+ name: string;
93
+ /**
94
+ * Messages buffer
95
+ */
96
+ protected messages: LogMessage[];
97
+ /**
98
+ * Grouped messages
99
+ */
100
+ protected groupedMessages: Record<string, LogMessage[]>;
101
+ /**
102
+ * Default channel configurations
103
+ */
104
+ protected defaultConfigurations: FileLogConfig;
105
+ /**
106
+ * Last write time
107
+ */
108
+ protected lastWriteTime: number;
109
+ /**
110
+ * Channel configurations
111
+ */
112
+ protected channelConfigurations: FileLogConfig;
113
+ /**
114
+ * A flag to determine if the file is being written
115
+ */
116
+ protected isWriting: boolean;
117
+ /**
118
+ * Get config value
119
+ */
120
+ protected config<K extends keyof FileLogConfig>(key: K): FileLogConfig[K];
121
+ /**
122
+ * Constructor
123
+ */
124
+ constructor(configurations?: FileLogConfig);
125
+ /**
126
+ * Check file size for file rotation
127
+ */
128
+ protected checkAndRotateFile(filePath?: string): Promise<void>;
129
+ /**
130
+ * Rotate log file
131
+ */
132
+ protected rotateLogFile(): Promise<void>;
133
+ /**
134
+ * Flush messages
135
+ */
136
+ protected initMessageFlush(): void;
137
+ /**
138
+ * Get file path
139
+ */
140
+ get filePath(): string;
141
+ /**
142
+ * Get max messages
143
+ */
144
+ protected get maxMessagesToWrite(): number;
145
+ /**
146
+ * Get file name
147
+ */
148
+ get fileName(): string;
149
+ /**
150
+ * Get file extension
151
+ */
152
+ get extension(): string;
153
+ /**
154
+ * Get content
155
+ */
156
+ protected get content(): string;
157
+ /**
158
+ * Get storage path
159
+ */
160
+ get storagePath(): string;
161
+ /**
162
+ * {@inheritdoc}
163
+ */
164
+ protected init(): Promise<void>;
165
+ /**
166
+ * Set configurations
167
+ */
168
+ configurations(configurations: FileLogConfig): this;
169
+ /**
170
+ * {@inheritdoc}
171
+ */
172
+ log(module: string, action: string, message: any, level: LogLevel): Promise<void>;
173
+ /**
174
+ * Check if messages should be written
175
+ */
176
+ protected checkIfMessagesShouldBeWritten(): Promise<void>;
177
+ /**
178
+ * Should be called after messages are saved
179
+ */
180
+ protected onSave(): void;
181
+ /**
182
+ * Check if messages should be grouped
183
+ */
184
+ protected get messagedShouldBeGrouped(): boolean;
185
+ /**
186
+ * Write messages to the file
187
+ */
188
+ protected writeMessagesToFile(): Promise<void>;
189
+ /**
190
+ * Write grouped messages to the file
191
+ */
192
+ protected writeGroupedMessagesToFile(): Promise<void>;
193
+ /**
194
+ * Prepare grouped messages
195
+ */
196
+ protected prepareGroupedMessages(): void;
197
+ /**
198
+ * Start writing to the file
199
+ */
200
+ protected write(filePath: string, content: string): Promise<unknown>;
201
+ }
202
+ //# sourceMappingURL=file-log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-log.d.ts","sourceRoot":"","sources":["../../src/channels/file-log.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,315 @@
1
+ import {ensureDirectoryAsync}from'@mongez/fs';import dayjs from'dayjs';import fs from'fs';import {EOL}from'os';import {LogChannel}from'../LogChannel.js';import path from'path';class FileLog extends LogChannel {
2
+ /**
3
+ * {@inheritdoc}
4
+ */
5
+ name = "file";
6
+ /**
7
+ * Messages buffer
8
+ */
9
+ messages = [];
10
+ /**
11
+ * Grouped messages
12
+ */
13
+ groupedMessages = {};
14
+ /**
15
+ * Default channel configurations
16
+ */
17
+ defaultConfigurations = {
18
+ storagePath: process.cwd() + "/storage/logs",
19
+ rotate: true,
20
+ name: "app",
21
+ extension: "log",
22
+ chunk: "single",
23
+ maxMessagesToWrite: 100,
24
+ // maxFileSize: 10 * 1024 * 1024, // 10MB
25
+ maxFileSize: 10,
26
+ get rotateFileName() {
27
+ return dayjs().format("DD-MM-YYYY");
28
+ },
29
+ dateFormat: {
30
+ date: "DD-MM-YYYY",
31
+ time: "HH:mm:ss",
32
+ },
33
+ };
34
+ /**
35
+ * Last write time
36
+ */
37
+ lastWriteTime = Date.now();
38
+ /**
39
+ * Channel configurations
40
+ */
41
+ channelConfigurations = {};
42
+ /**
43
+ * A flag to determine if the file is being written
44
+ */
45
+ isWriting = false;
46
+ /**
47
+ * Get config value
48
+ */
49
+ config(key) {
50
+ return this.channelConfigurations[key] ?? this.defaultConfigurations[key];
51
+ }
52
+ /**
53
+ * Constructor
54
+ */
55
+ constructor(configurations) {
56
+ super();
57
+ if (configurations) {
58
+ this.configurations(configurations);
59
+ }
60
+ this.init();
61
+ this.initMessageFlush();
62
+ }
63
+ /**
64
+ * Check file size for file rotation
65
+ */
66
+ async checkAndRotateFile(filePath = this.filePath) {
67
+ if (!this.config("rotate"))
68
+ return;
69
+ try {
70
+ const stats = await fs.promises.stat(filePath);
71
+ if (stats.size >= this.config("maxFileSize")) {
72
+ await this.rotateLogFile();
73
+ }
74
+ }
75
+ catch (error) {
76
+ if (error.code === "ENOENT") {
77
+ // File doesn't exist, this can be normal if it's a new file
78
+ console.log("Log file does not exist, will be created on first write.");
79
+ }
80
+ else {
81
+ console.error("Error checking log file:", error);
82
+ }
83
+ }
84
+ }
85
+ /**
86
+ * Rotate log file
87
+ */
88
+ async rotateLogFile() {
89
+ let fileName = `${this.fileName}-${this.config("rotateFileName")}-${Date.now()}`;
90
+ const extension = this.extension;
91
+ const rotatedFilePath = path.join(this.storagePath, `${fileName}.${extension}`);
92
+ await fs.promises.rename(this.filePath, rotatedFilePath).catch((error) => {
93
+ console.error("Error rotating file:", error);
94
+ });
95
+ }
96
+ /**
97
+ * Flush messages
98
+ */
99
+ initMessageFlush() {
100
+ setInterval(() => {
101
+ if (this.messages.length > 0 &&
102
+ (this.messages.length >= this.maxMessagesToWrite ||
103
+ Date.now() - this.lastWriteTime > 5000)) {
104
+ this.writeMessagesToFile();
105
+ }
106
+ }, 5000); // Periodic check
107
+ }
108
+ /**
109
+ * Get file path
110
+ */
111
+ get filePath() {
112
+ let fileName = this.fileName;
113
+ const extension = this.extension;
114
+ return path.join(this.storagePath, `${fileName}.${extension}`);
115
+ }
116
+ /**
117
+ * Get max messages
118
+ */
119
+ get maxMessagesToWrite() {
120
+ return this.config("maxMessagesToWrite");
121
+ }
122
+ /**
123
+ * Get file name
124
+ */
125
+ get fileName() {
126
+ const debugLevel = this.config("chunk");
127
+ switch (debugLevel) {
128
+ case "single":
129
+ default:
130
+ return this.config("name");
131
+ case "daily":
132
+ return dayjs().format("DD-MM-YYYY");
133
+ case "hourly":
134
+ return dayjs().format("DD-MM-YYYY-HH");
135
+ }
136
+ }
137
+ /**
138
+ * Get file extension
139
+ */
140
+ get extension() {
141
+ return this.config("extension");
142
+ }
143
+ /**
144
+ * Get content
145
+ */
146
+ get content() {
147
+ return this.messages.map((message) => message.content).join(EOL) + EOL;
148
+ }
149
+ /**
150
+ * Get storage path
151
+ */
152
+ get storagePath() {
153
+ return this.config("storagePath");
154
+ }
155
+ /**
156
+ * {@inheritdoc}
157
+ */
158
+ async init() {
159
+ const logsDirectory = this.storagePath;
160
+ await ensureDirectoryAsync(logsDirectory);
161
+ }
162
+ /**
163
+ * Set configurations
164
+ */
165
+ configurations(configurations) {
166
+ this.channelConfigurations = {
167
+ ...this.channelConfigurations,
168
+ ...configurations,
169
+ dateFormat: {
170
+ ...this.channelConfigurations.dateFormat,
171
+ ...configurations.dateFormat,
172
+ },
173
+ };
174
+ return this;
175
+ }
176
+ /**
177
+ * {@inheritdoc}
178
+ */
179
+ async log(module, action, message, level) {
180
+ // check for debug mode
181
+ const allowedLevels = this.config("levels");
182
+ if (allowedLevels && !allowedLevels.includes(level))
183
+ return;
184
+ const filter = this.config("filter");
185
+ if (filter) {
186
+ const shouldBeLogged = filter({ level, module, action });
187
+ if (!shouldBeLogged)
188
+ return;
189
+ }
190
+ const date = dayjs().format((this.channelConfigurations.dateFormat.date || "DD-MM-YYY") +
191
+ " " +
192
+ (this.channelConfigurations.dateFormat.time || "HH:mm:ss"));
193
+ let content = `[${date}] [${level}] [${module}][${action}]: `;
194
+ let stack = "";
195
+ // check if message is an instance of Error
196
+ if (message instanceof Error) {
197
+ // in that case we need to store the error message and stack trace
198
+ content += message.message + EOL;
199
+ content += `[trace]` + EOL;
200
+ content += message.stack;
201
+ stack = message.stack ?? "";
202
+ }
203
+ else {
204
+ content += message;
205
+ }
206
+ this.messages.push({
207
+ content,
208
+ level,
209
+ date,
210
+ module,
211
+ action,
212
+ stack,
213
+ });
214
+ await this.checkIfMessagesShouldBeWritten(); // Immediate check on buffer size
215
+ }
216
+ /**
217
+ * Check if messages should be written
218
+ */
219
+ async checkIfMessagesShouldBeWritten() {
220
+ if (this.messages.length >= this.maxMessagesToWrite ||
221
+ Date.now() - this.lastWriteTime > 5000) {
222
+ await this.writeMessagesToFile();
223
+ }
224
+ }
225
+ /**
226
+ * Should be called after messages are saved
227
+ */
228
+ onSave() {
229
+ this.messages = [];
230
+ this.groupedMessages = {};
231
+ this.isWriting = false;
232
+ this.lastWriteTime = Date.now();
233
+ }
234
+ /**
235
+ * Check if messages should be grouped
236
+ */
237
+ get messagedShouldBeGrouped() {
238
+ return Number(this.config("groupBy")?.length) > 0;
239
+ }
240
+ /**
241
+ * Write messages to the file
242
+ */
243
+ async writeMessagesToFile() {
244
+ if (this.messages.length === 0 || this.isWriting)
245
+ return;
246
+ this.isWriting = true;
247
+ if (this.messagedShouldBeGrouped) {
248
+ return await this.writeGroupedMessagesToFile();
249
+ }
250
+ await this.checkAndRotateFile(); // Ensure we check file size before writing
251
+ try {
252
+ await this.write(this.filePath, this.content);
253
+ this.onSave();
254
+ }
255
+ catch (error) {
256
+ console.error("Failed to write log:", error);
257
+ // Implement fallback logic here
258
+ this.isWriting = false;
259
+ }
260
+ }
261
+ /**
262
+ * Write grouped messages to the file
263
+ */
264
+ async writeGroupedMessagesToFile() {
265
+ // first step, is to group the messages
266
+ this.prepareGroupedMessages();
267
+ // now each key in the grouped messages, represents the directory path that should extend the storage path
268
+ for (const key in this.groupedMessages) {
269
+ const directoryPath = path.join(this.storagePath, key);
270
+ await ensureDirectoryAsync(directoryPath);
271
+ const filePath = path.join(directoryPath, `${this.fileName}.${this.extension}`);
272
+ await this.checkAndRotateFile(filePath); // Ensure we check file size before writing
273
+ const content = this.groupedMessages[key].map((message) => message.content).join(EOL) +
274
+ EOL;
275
+ console.log("content", content);
276
+ try {
277
+ await this.write(filePath, content);
278
+ }
279
+ catch (error) {
280
+ console.error("Failed to write log:", error);
281
+ }
282
+ }
283
+ this.onSave();
284
+ this.isWriting = false;
285
+ }
286
+ /**
287
+ * Prepare grouped messages
288
+ */
289
+ prepareGroupedMessages() {
290
+ this.messages.forEach((message) => {
291
+ const key = this.config("groupBy")
292
+ .map((groupKey) => encodeURIComponent(message[groupKey]))
293
+ .join("/");
294
+ this.groupedMessages[key] = this.groupedMessages[key] || [];
295
+ this.groupedMessages[key].push(message);
296
+ });
297
+ }
298
+ /**
299
+ * Start writing to the file
300
+ */
301
+ async write(filePath, content) {
302
+ return new Promise((resolve, reject) => {
303
+ const writer = fs.createWriteStream(filePath, { flags: "a" });
304
+ writer.write(content, (error) => {
305
+ writer.end();
306
+ if (error) {
307
+ reject(error);
308
+ }
309
+ else {
310
+ resolve(true);
311
+ }
312
+ });
313
+ });
314
+ }
315
+ }export{FileLog};//# sourceMappingURL=file-log.js.map