@warlock.js/logger 4.0.171 → 4.1.1
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/README.md +145 -422
- package/cjs/index.cjs +1003 -0
- package/cjs/index.cjs.map +1 -0
- package/esm/channels/console-log.d.mts +40 -0
- package/esm/channels/console-log.d.mts.map +1 -0
- package/esm/channels/console-log.mjs +51 -0
- package/esm/channels/console-log.mjs.map +1 -0
- package/esm/channels/file-log.d.mts +194 -0
- package/esm/channels/file-log.d.mts.map +1 -0
- package/esm/channels/file-log.mjs +267 -0
- package/esm/channels/file-log.mjs.map +1 -0
- package/esm/channels/index.mjs +5 -0
- package/esm/channels/json-file-log.d.mts +33 -0
- package/esm/channels/json-file-log.d.mts.map +1 -0
- package/esm/channels/json-file-log.mjs +137 -0
- package/esm/channels/json-file-log.mjs.map +1 -0
- package/esm/index.d.mts +11 -0
- package/esm/index.mjs +13 -0
- package/esm/log-channel.d.mts +78 -0
- package/esm/log-channel.d.mts.map +1 -0
- package/esm/log-channel.mjs +75 -0
- package/esm/log-channel.mjs.map +1 -0
- package/esm/logger.d.mts +184 -0
- package/esm/logger.d.mts.map +1 -0
- package/esm/logger.mjs +282 -0
- package/esm/logger.mjs.map +1 -0
- package/esm/redact/redact.d.mts +25 -0
- package/esm/redact/redact.d.mts.map +1 -0
- package/esm/redact/redact.mjs +109 -0
- package/esm/redact/redact.mjs.map +1 -0
- package/esm/types.d.mts +129 -0
- package/esm/types.d.mts.map +1 -0
- package/esm/utils/capture-unhandled-errors.d.mts +16 -0
- package/esm/utils/capture-unhandled-errors.d.mts.map +1 -0
- package/esm/utils/capture-unhandled-errors.mjs +26 -0
- package/esm/utils/capture-unhandled-errors.mjs.map +1 -0
- package/esm/utils/clear-message.d.mts +8 -0
- package/esm/utils/clear-message.d.mts.map +1 -0
- package/esm/utils/clear-message.mjs +12 -0
- package/esm/utils/clear-message.mjs.map +1 -0
- package/esm/utils/index.mjs +5 -0
- package/esm/utils/safe-json-stringify.d.mts +14 -0
- package/esm/utils/safe-json-stringify.d.mts.map +1 -0
- package/esm/utils/safe-json-stringify.mjs +35 -0
- package/esm/utils/safe-json-stringify.mjs.map +1 -0
- package/llms-full.txt +1296 -0
- package/llms.txt +19 -0
- package/package.json +39 -39
- package/skills/capture-unhandled-errors/SKILL.md +103 -0
- package/skills/configure-logger/SKILL.md +105 -0
- package/skills/filter-log-entries/SKILL.md +120 -0
- package/skills/flush-logs-on-shutdown/SKILL.md +91 -0
- package/skills/logger-basics/SKILL.md +85 -0
- package/skills/overview/SKILL.md +86 -0
- package/skills/pick-log-channel/SKILL.md +139 -0
- package/skills/redact-sensitive-log-fields/SKILL.md +122 -0
- package/skills/test-logging-code/SKILL.md +169 -0
- package/skills/use-log-helpers/SKILL.md +66 -0
- package/skills/write-custom-log-channel/SKILL.md +160 -0
- package/cjs/channels/console-log.d.ts +0 -17
- package/cjs/channels/console-log.d.ts.map +0 -1
- package/cjs/channels/console-log.js +0 -47
- package/cjs/channels/console-log.js.map +0 -1
- package/cjs/channels/file-log.d.ts +0 -171
- package/cjs/channels/file-log.d.ts.map +0 -1
- package/cjs/channels/file-log.js +0 -293
- package/cjs/channels/file-log.js.map +0 -1
- package/cjs/channels/index.d.ts +0 -4
- package/cjs/channels/index.d.ts.map +0 -1
- package/cjs/channels/json-file-log.d.ts +0 -33
- package/cjs/channels/json-file-log.d.ts.map +0 -1
- package/cjs/channels/json-file-log.js +0 -164
- package/cjs/channels/json-file-log.js.map +0 -1
- package/cjs/index.d.ts +0 -6
- package/cjs/index.d.ts.map +0 -1
- package/cjs/index.js +0 -1
- package/cjs/index.js.map +0 -1
- package/cjs/log-channel.d.ts +0 -67
- package/cjs/log-channel.d.ts.map +0 -1
- package/cjs/log-channel.js +0 -88
- package/cjs/log-channel.js.map +0 -1
- package/cjs/logger.d.ts +0 -62
- package/cjs/logger.d.ts.map +0 -1
- package/cjs/logger.js +0 -124
- package/cjs/logger.js.map +0 -1
- package/cjs/types.d.ts +0 -104
- package/cjs/types.d.ts.map +0 -1
- package/cjs/utils/capture-unhandled-errors.d.ts +0 -2
- package/cjs/utils/capture-unhandled-errors.d.ts.map +0 -1
- package/cjs/utils/capture-unhandled-errors.js +0 -12
- package/cjs/utils/capture-unhandled-errors.js.map +0 -1
- package/cjs/utils/clear-message.d.ts +0 -5
- package/cjs/utils/clear-message.d.ts.map +0 -1
- package/cjs/utils/clear-message.js +0 -9
- package/cjs/utils/clear-message.js.map +0 -1
- package/cjs/utils/index.d.ts +0 -3
- package/cjs/utils/index.d.ts.map +0 -1
- package/esm/channels/console-log.d.ts +0 -17
- package/esm/channels/console-log.d.ts.map +0 -1
- package/esm/channels/console-log.js +0 -47
- package/esm/channels/console-log.js.map +0 -1
- package/esm/channels/file-log.d.ts +0 -171
- package/esm/channels/file-log.d.ts.map +0 -1
- package/esm/channels/file-log.js +0 -293
- package/esm/channels/file-log.js.map +0 -1
- package/esm/channels/index.d.ts +0 -4
- package/esm/channels/index.d.ts.map +0 -1
- package/esm/channels/json-file-log.d.ts +0 -33
- package/esm/channels/json-file-log.d.ts.map +0 -1
- package/esm/channels/json-file-log.js +0 -164
- package/esm/channels/json-file-log.js.map +0 -1
- package/esm/index.d.ts +0 -6
- package/esm/index.d.ts.map +0 -1
- package/esm/index.js +0 -1
- package/esm/index.js.map +0 -1
- package/esm/log-channel.d.ts +0 -67
- package/esm/log-channel.d.ts.map +0 -1
- package/esm/log-channel.js +0 -88
- package/esm/log-channel.js.map +0 -1
- package/esm/logger.d.ts +0 -62
- package/esm/logger.d.ts.map +0 -1
- package/esm/logger.js +0 -124
- package/esm/logger.js.map +0 -1
- package/esm/types.d.ts +0 -104
- package/esm/types.d.ts.map +0 -1
- package/esm/utils/capture-unhandled-errors.d.ts +0 -2
- package/esm/utils/capture-unhandled-errors.d.ts.map +0 -1
- package/esm/utils/capture-unhandled-errors.js +0 -12
- package/esm/utils/capture-unhandled-errors.js.map +0 -1
- package/esm/utils/clear-message.d.ts +0 -5
- package/esm/utils/clear-message.d.ts.map +0 -1
- package/esm/utils/clear-message.js +0 -9
- package/esm/utils/clear-message.js.map +0 -1
- package/esm/utils/index.d.ts +0 -3
- package/esm/utils/index.d.ts.map +0 -1
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { LogChannel } from "../log-channel.mjs";
|
|
2
|
+
import { ensureDirectoryAsync } from "@warlock.js/fs";
|
|
3
|
+
import dayjs from "dayjs";
|
|
4
|
+
import fs from "fs";
|
|
5
|
+
import { EOL } from "os";
|
|
6
|
+
import path from "path";
|
|
7
|
+
|
|
8
|
+
//#region ../../@warlock.js/logger/src/channels/file-log.ts
|
|
9
|
+
var FileLog = class extends LogChannel {
|
|
10
|
+
constructor(..._args) {
|
|
11
|
+
super(..._args);
|
|
12
|
+
this.name = "file";
|
|
13
|
+
this.messages = [];
|
|
14
|
+
this.groupedMessages = {};
|
|
15
|
+
this.defaultConfigurations = {
|
|
16
|
+
storagePath: process.cwd() + "/storage/logs",
|
|
17
|
+
rotate: true,
|
|
18
|
+
name: "app",
|
|
19
|
+
extension: "log",
|
|
20
|
+
chunk: "single",
|
|
21
|
+
maxMessagesToWrite: 100,
|
|
22
|
+
filter: () => true,
|
|
23
|
+
maxFileSize: 10 * 1024 * 1024,
|
|
24
|
+
get rotateFileName() {
|
|
25
|
+
return dayjs().format("DD-MM-YYYY");
|
|
26
|
+
},
|
|
27
|
+
dateFormat: {
|
|
28
|
+
date: "DD-MM-YYYY",
|
|
29
|
+
time: "HH:mm:ss"
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
this.lastWriteTime = Date.now();
|
|
33
|
+
this.isWriting = false;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Check file size for file rotation
|
|
37
|
+
*/
|
|
38
|
+
async checkAndRotateFile(filePath = this.filePath) {
|
|
39
|
+
if (!this.config("rotate")) return;
|
|
40
|
+
try {
|
|
41
|
+
if ((await fs.promises.stat(filePath)).size >= this.config("maxFileSize")) await this.rotateLogFile();
|
|
42
|
+
} catch (error) {
|
|
43
|
+
if (error.code !== "ENOENT") console.error("Error checking log file:", error);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Rotate log file
|
|
48
|
+
*/
|
|
49
|
+
async rotateLogFile() {
|
|
50
|
+
const fileName = `${this.fileName}-${this.config("rotateFileName")}-${Date.now()}`;
|
|
51
|
+
const extension = this.extension;
|
|
52
|
+
const rotatedFilePath = path.join(this.storagePath, `${fileName}.${extension}`);
|
|
53
|
+
await fs.promises.rename(this.filePath, rotatedFilePath).catch((error) => {
|
|
54
|
+
console.error("Error rotating file:", error);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Flush messages
|
|
59
|
+
*
|
|
60
|
+
* Starts a periodic re-check so low-traffic channels don't sit on buffered
|
|
61
|
+
* entries indefinitely. The handle is stored on the instance so `dispose()`
|
|
62
|
+
* can stop it — without this, every channel leaks a timer for the lifetime
|
|
63
|
+
* of the process.
|
|
64
|
+
*/
|
|
65
|
+
initMessageFlush() {
|
|
66
|
+
this.flushIntervalHandle = setInterval(() => {
|
|
67
|
+
if (this.messages.length > 0 && (this.messages.length >= this.maxMessagesToWrite || Date.now() - this.lastWriteTime > 5e3)) this.writeMessagesToFile();
|
|
68
|
+
}, 5e3);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Stop the background flush interval and drain any buffered entries.
|
|
72
|
+
*
|
|
73
|
+
* Call this when discarding a channel (e.g. reconfiguring the logger at
|
|
74
|
+
* runtime) so the 5-second timer doesn't keep the event loop alive. Safe to
|
|
75
|
+
* call more than once.
|
|
76
|
+
*/
|
|
77
|
+
dispose() {
|
|
78
|
+
if (this.flushIntervalHandle) {
|
|
79
|
+
clearInterval(this.flushIntervalHandle);
|
|
80
|
+
this.flushIntervalHandle = void 0;
|
|
81
|
+
}
|
|
82
|
+
this.flushSync();
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Get file path
|
|
86
|
+
*/
|
|
87
|
+
get filePath() {
|
|
88
|
+
const fileName = this.fileName;
|
|
89
|
+
const extension = this.extension;
|
|
90
|
+
return path.join(this.storagePath, `${fileName}.${extension}`);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Get max messages
|
|
94
|
+
*/
|
|
95
|
+
get maxMessagesToWrite() {
|
|
96
|
+
return this.config("maxMessagesToWrite");
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Get file name
|
|
100
|
+
*/
|
|
101
|
+
get fileName() {
|
|
102
|
+
switch (this.config("chunk")) {
|
|
103
|
+
case "single":
|
|
104
|
+
default: return this.config("name");
|
|
105
|
+
case "daily": return dayjs().format("DD-MM-YYYY");
|
|
106
|
+
case "hourly": return dayjs().format("DD-MM-YYYY-HH-00-00-a");
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Get file extension
|
|
111
|
+
*/
|
|
112
|
+
get extension() {
|
|
113
|
+
return this.config("extension");
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Get content
|
|
117
|
+
*/
|
|
118
|
+
get content() {
|
|
119
|
+
return this.messages.map((message) => message.content).join(EOL) + EOL;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Get storage path
|
|
123
|
+
*/
|
|
124
|
+
get storagePath() {
|
|
125
|
+
return this.config("storagePath");
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* {@inheritdoc}
|
|
129
|
+
*/
|
|
130
|
+
async init() {
|
|
131
|
+
const logsDirectory = this.storagePath;
|
|
132
|
+
await ensureDirectoryAsync(logsDirectory);
|
|
133
|
+
this.initMessageFlush();
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Synchronously flush messages
|
|
137
|
+
*/
|
|
138
|
+
flushSync() {
|
|
139
|
+
if (this.messages.length === 0 && Object.keys(this.groupedMessages).length === 0) return;
|
|
140
|
+
if (this.messagedShouldBeGrouped) {
|
|
141
|
+
this.prepareGroupedMessages();
|
|
142
|
+
for (const key in this.groupedMessages) {
|
|
143
|
+
const directoryPath = path.join(this.storagePath, key);
|
|
144
|
+
fs.mkdirSync(directoryPath, { recursive: true });
|
|
145
|
+
const filePath = path.join(directoryPath, `${this.fileName}.${this.extension}`);
|
|
146
|
+
const content = this.groupedMessages[key].map((message) => message.content).join(EOL) + EOL;
|
|
147
|
+
fs.appendFileSync(filePath, content);
|
|
148
|
+
}
|
|
149
|
+
} else {
|
|
150
|
+
fs.mkdirSync(this.storagePath, { recursive: true });
|
|
151
|
+
fs.appendFileSync(this.filePath, this.content);
|
|
152
|
+
}
|
|
153
|
+
this.onSave();
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* {@inheritdoc}
|
|
157
|
+
*/
|
|
158
|
+
async log(data) {
|
|
159
|
+
const { module, action, message, type: level, context } = data;
|
|
160
|
+
if (!this.shouldBeLogged(data)) return;
|
|
161
|
+
const { date: dateFormat, time } = this.getDateAndTimeFormat();
|
|
162
|
+
const date = dayjs().format(dateFormat + " " + time);
|
|
163
|
+
let content = `[${date}] [${level}] [${module}][${action}]: `;
|
|
164
|
+
let stack;
|
|
165
|
+
if (message instanceof Error) {
|
|
166
|
+
content += message.message + EOL;
|
|
167
|
+
content += `[trace]` + EOL;
|
|
168
|
+
content += message.stack;
|
|
169
|
+
stack = message.stack;
|
|
170
|
+
} else content += message;
|
|
171
|
+
this.messages.push({
|
|
172
|
+
content,
|
|
173
|
+
level,
|
|
174
|
+
date,
|
|
175
|
+
module,
|
|
176
|
+
action,
|
|
177
|
+
stack,
|
|
178
|
+
context,
|
|
179
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
180
|
+
});
|
|
181
|
+
await this.checkIfMessagesShouldBeWritten();
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Check if messages should be written
|
|
185
|
+
*/
|
|
186
|
+
async checkIfMessagesShouldBeWritten() {
|
|
187
|
+
if (this.messages.length >= this.maxMessagesToWrite || Date.now() - this.lastWriteTime > 5e3) await this.writeMessagesToFile();
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Should be called after messages are saved
|
|
191
|
+
*/
|
|
192
|
+
onSave() {
|
|
193
|
+
this.messages = [];
|
|
194
|
+
this.groupedMessages = {};
|
|
195
|
+
this.isWriting = false;
|
|
196
|
+
this.lastWriteTime = Date.now();
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Check if messages should be grouped
|
|
200
|
+
*/
|
|
201
|
+
get messagedShouldBeGrouped() {
|
|
202
|
+
return Number(this.config("groupBy")?.length) > 0;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Write messages to the file
|
|
206
|
+
*/
|
|
207
|
+
async writeMessagesToFile() {
|
|
208
|
+
if (this.messages.length === 0 || this.isWriting || !this.isInitialized) return;
|
|
209
|
+
this.isWriting = true;
|
|
210
|
+
if (this.messagedShouldBeGrouped) return await this.writeGroupedMessagesToFile();
|
|
211
|
+
await this.checkAndRotateFile();
|
|
212
|
+
try {
|
|
213
|
+
await this.write(this.filePath, this.content);
|
|
214
|
+
this.onSave();
|
|
215
|
+
} catch (error) {
|
|
216
|
+
console.error("Failed to write log:", error);
|
|
217
|
+
this.isWriting = false;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Write grouped messages to the file
|
|
222
|
+
*/
|
|
223
|
+
async writeGroupedMessagesToFile() {
|
|
224
|
+
this.prepareGroupedMessages();
|
|
225
|
+
for (const key in this.groupedMessages) {
|
|
226
|
+
const directoryPath = path.join(this.storagePath, key);
|
|
227
|
+
await ensureDirectoryAsync(directoryPath);
|
|
228
|
+
const filePath = path.join(directoryPath, `${this.fileName}.${this.extension}`);
|
|
229
|
+
await this.checkAndRotateFile(filePath);
|
|
230
|
+
const content = this.groupedMessages[key].map((message) => message.content).join(EOL) + EOL;
|
|
231
|
+
try {
|
|
232
|
+
await this.write(filePath, content);
|
|
233
|
+
} catch (error) {
|
|
234
|
+
console.error("Failed to write log:", error);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
this.onSave();
|
|
238
|
+
this.isWriting = false;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Prepare grouped messages
|
|
242
|
+
*/
|
|
243
|
+
prepareGroupedMessages() {
|
|
244
|
+
this.messages.forEach((message) => {
|
|
245
|
+
const key = this.config("groupBy").map((groupKey) => encodeURIComponent(message[groupKey])).join("/");
|
|
246
|
+
this.groupedMessages[key] = this.groupedMessages[key] || [];
|
|
247
|
+
this.groupedMessages[key].push(message);
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Start writing to the file
|
|
252
|
+
*/
|
|
253
|
+
async write(filePath, content) {
|
|
254
|
+
return new Promise((resolve, reject) => {
|
|
255
|
+
const writer = fs.createWriteStream(filePath, { flags: "a" });
|
|
256
|
+
writer.write(content, (error) => {
|
|
257
|
+
writer.end();
|
|
258
|
+
if (error) reject(error);
|
|
259
|
+
else resolve(true);
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
//#endregion
|
|
266
|
+
export { FileLog };
|
|
267
|
+
//# sourceMappingURL=file-log.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-log.mjs","names":[],"sources":["../../../../../../@warlock.js/logger/src/channels/file-log.ts"],"sourcesContent":["import { ensureDirectoryAsync } from \"@warlock.js/fs\";\r\nimport dayjs from \"dayjs\";\r\nimport fs from \"fs\";\r\nimport { EOL } from \"os\";\r\nimport path from \"path\";\r\nimport { LogChannel } from \"../log-channel\";\r\nimport type {\r\n BasicLogConfigurations,\r\n LogContract,\r\n LoggingData,\r\n LogLevel,\r\n LogMessage,\r\n} from \"../types\";\r\n\r\n// TODO: Add max messages per file before rotation\r\n\r\nexport type FileLogConfig = BasicLogConfigurations & {\r\n storagePath?: string;\r\n /**\r\n * File name, without extension\r\n */\r\n name?: string;\r\n /**\r\n * chunk mode\r\n * If set to `single`, the logs will be created in a single file, unless the rotate is set to true\r\n * If set to `daily`, the logs will be created in a daily file, unless the rotate is set to true\r\n * If set to `hourly`, the logs will be created in an hourly file, unless the rotate is set to true\r\n * @default single\r\n */\r\n chunk?: \"single\" | \"daily\" | \"hourly\";\r\n /**\r\n * Whether to rotate the file\r\n *\r\n * @default true\r\n */\r\n rotate?: boolean;\r\n /**\r\n * File Extension\r\n *\r\n * @default log\r\n */\r\n extension?: string;\r\n /**\r\n * If rotate is set, the rotate name will be added to the file name suffixed with `-`\r\n *\r\n * @default DD-MM-YYYY\r\n */\r\n rotateFileName?: string;\r\n /**\r\n * Max file size before rotating the file\r\n *\r\n * @default 10MB\r\n */\r\n maxFileSize?: number;\r\n /**\r\n * Set the max messages that needs to be added before writing to the file\r\n *\r\n * @default 100\r\n */\r\n maxMessagesToWrite?: number;\r\n /**\r\n * Group logs by\r\n * Please note that the order matters here\r\n * For example, if you set `groupBy: ['level', 'module']`, the logs will be added in level name first, then by module\r\n *\r\n * @default none\r\n */\r\n groupBy?: (\"level\" | \"module\" | \"action\")[];\r\n /**\r\n * Define what levels should be logged\r\n *\r\n * @default all\r\n */\r\n levels?: LogLevel[];\r\n /**\r\n * Date and time format\r\n */\r\n dateFormat?: {\r\n date?: string;\r\n time?: string;\r\n };\r\n};\r\n\r\nexport class FileLog extends LogChannel<FileLogConfig> implements LogContract {\r\n /**\r\n * {@inheritdoc}\r\n */\r\n public name = \"file\";\r\n\r\n /**\r\n * Messages buffer\r\n */\r\n protected messages: LogMessage[] = [];\r\n\r\n /**\r\n * Grouped messages\r\n */\r\n protected groupedMessages: Record<string, LogMessage[]> = {};\r\n\r\n /**\r\n * Default channel configurations\r\n */\r\n protected defaultConfigurations: FileLogConfig = {\r\n storagePath: process.cwd() + \"/storage/logs\",\r\n rotate: true,\r\n name: \"app\",\r\n extension: \"log\",\r\n chunk: \"single\",\r\n maxMessagesToWrite: 100,\r\n filter: () => true,\r\n maxFileSize: 10 * 1024 * 1024, // 10MB\r\n get rotateFileName() {\r\n return dayjs().format(\"DD-MM-YYYY\");\r\n },\r\n dateFormat: {\r\n date: \"DD-MM-YYYY\",\r\n time: \"HH:mm:ss\",\r\n },\r\n };\r\n\r\n /**\r\n * Last write time\r\n */\r\n protected lastWriteTime = Date.now();\r\n\r\n /**\r\n * A flag to determine if the file is being written\r\n */\r\n protected isWriting = false;\r\n\r\n /**\r\n * Handle for the periodic flush interval. Stored so it can be cleared\r\n * in `dispose()` — long-lived processes that create channels dynamically\r\n * would otherwise leak one timer per channel.\r\n */\r\n protected flushIntervalHandle?: NodeJS.Timeout;\r\n\r\n /**\r\n * Check file size for file rotation\r\n */\r\n protected async checkAndRotateFile(filePath = this.filePath) {\r\n if (!this.config(\"rotate\")) return;\r\n\r\n try {\r\n const stats = await fs.promises.stat(filePath);\r\n if (stats.size >= this.config(\"maxFileSize\")!) {\r\n await this.rotateLogFile();\r\n }\r\n } catch (error: any) {\r\n // ENOENT is expected when the file hasn't been created yet — there is\r\n // nothing to rotate, so stay silent. Surface anything else.\r\n if (error.code !== \"ENOENT\") {\r\n console.error(\"Error checking log file:\", error);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Rotate log file\r\n */\r\n protected async rotateLogFile() {\r\n const fileName = `${this.fileName}-${this.config(\"rotateFileName\")}-${Date.now()}`;\r\n\r\n const extension = this.extension;\r\n\r\n const rotatedFilePath = path.join(this.storagePath, `${fileName}.${extension}`);\r\n\r\n await fs.promises.rename(this.filePath, rotatedFilePath).catch((error) => {\r\n console.error(\"Error rotating file:\", error);\r\n });\r\n }\r\n\r\n /**\r\n * Flush messages\r\n *\r\n * Starts a periodic re-check so low-traffic channels don't sit on buffered\r\n * entries indefinitely. The handle is stored on the instance so `dispose()`\r\n * can stop it — without this, every channel leaks a timer for the lifetime\r\n * of the process.\r\n */\r\n protected initMessageFlush() {\r\n this.flushIntervalHandle = setInterval(() => {\r\n if (\r\n this.messages.length > 0 &&\r\n (this.messages.length >= this.maxMessagesToWrite || Date.now() - this.lastWriteTime > 5000)\r\n ) {\r\n this.writeMessagesToFile();\r\n }\r\n }, 5000);\r\n }\r\n\r\n /**\r\n * Stop the background flush interval and drain any buffered entries.\r\n *\r\n * Call this when discarding a channel (e.g. reconfiguring the logger at\r\n * runtime) so the 5-second timer doesn't keep the event loop alive. Safe to\r\n * call more than once.\r\n */\r\n public dispose(): void {\r\n if (this.flushIntervalHandle) {\r\n clearInterval(this.flushIntervalHandle);\r\n this.flushIntervalHandle = undefined;\r\n }\r\n\r\n this.flushSync();\r\n }\r\n\r\n /**\r\n * Get file path\r\n */\r\n public get filePath() {\r\n const fileName = this.fileName;\r\n\r\n const extension = this.extension;\r\n\r\n return path.join(this.storagePath, `${fileName}.${extension}`);\r\n }\r\n\r\n /**\r\n * Get max messages\r\n */\r\n protected get maxMessagesToWrite(): number {\r\n return this.config(\"maxMessagesToWrite\")!;\r\n }\r\n\r\n /**\r\n * Get file name\r\n */\r\n public get fileName(): string {\r\n const debugLevel = this.config(\"chunk\")!;\r\n\r\n switch (debugLevel) {\r\n case \"single\":\r\n default:\r\n return this.config(\"name\")!;\r\n case \"daily\":\r\n return dayjs().format(\"DD-MM-YYYY\");\r\n case \"hourly\":\r\n return dayjs().format(\"DD-MM-YYYY-HH-00-00-a\");\r\n }\r\n }\r\n\r\n /**\r\n * Get file extension\r\n */\r\n public get extension(): string {\r\n return this.config(\"extension\")!;\r\n }\r\n\r\n /**\r\n * Get content\r\n */\r\n protected get content() {\r\n return this.messages.map((message) => message.content).join(EOL) + EOL;\r\n }\r\n\r\n /**\r\n * Get storage path\r\n */\r\n public get storagePath(): string {\r\n return this.config(\"storagePath\")!;\r\n }\r\n\r\n /**\r\n * {@inheritdoc}\r\n */\r\n protected async init() {\r\n const logsDirectory = this.storagePath;\r\n\r\n await ensureDirectoryAsync(logsDirectory);\r\n\r\n this.initMessageFlush();\r\n }\r\n\r\n /**\r\n * Synchronously flush messages\r\n */\r\n public flushSync(): void {\r\n if (this.messages.length === 0 && Object.keys(this.groupedMessages).length === 0) return;\r\n\r\n if (this.messagedShouldBeGrouped) {\r\n this.prepareGroupedMessages();\r\n for (const key in this.groupedMessages) {\r\n const directoryPath = path.join(this.storagePath, key);\r\n fs.mkdirSync(directoryPath, { recursive: true });\r\n const filePath = path.join(directoryPath, `${this.fileName}.${this.extension}`);\r\n const content = this.groupedMessages[key].map((message) => message.content).join(EOL) + EOL;\r\n fs.appendFileSync(filePath, content);\r\n }\r\n } else {\r\n fs.mkdirSync(this.storagePath, { recursive: true });\r\n fs.appendFileSync(this.filePath, this.content);\r\n }\r\n\r\n this.onSave();\r\n }\r\n\r\n /**\r\n * {@inheritdoc}\r\n */\r\n public async log(data: LoggingData) {\r\n const { module, action, message, type: level, context } = data;\r\n\r\n if (!this.shouldBeLogged(data)) return;\r\n\r\n const { date: dateFormat, time } = this.getDateAndTimeFormat();\r\n\r\n const date = dayjs().format(dateFormat + \" \" + time);\r\n\r\n let content = `[${date}] [${level}] [${module}][${action}]: `;\r\n\r\n let stack: string | undefined;\r\n\r\n // check if message is an instance of Error\r\n if (message instanceof Error) {\r\n // in that case we need to store the error message and stack trace\r\n content += message.message + EOL;\r\n content += `[trace]` + EOL;\r\n content += message.stack;\r\n stack = message.stack;\r\n } else {\r\n content += message;\r\n }\r\n\r\n this.messages.push({\r\n content,\r\n level,\r\n date,\r\n module,\r\n action,\r\n stack,\r\n context,\r\n timestamp: new Date().toISOString(),\r\n });\r\n\r\n await this.checkIfMessagesShouldBeWritten(); // Immediate check on buffer size\r\n }\r\n\r\n /**\r\n * Check if messages should be written\r\n */\r\n protected async checkIfMessagesShouldBeWritten() {\r\n if (this.messages.length >= this.maxMessagesToWrite || Date.now() - this.lastWriteTime > 5000) {\r\n await this.writeMessagesToFile();\r\n }\r\n }\r\n\r\n /**\r\n * Should be called after messages are saved\r\n */\r\n protected onSave() {\r\n this.messages = [];\r\n this.groupedMessages = {};\r\n this.isWriting = false;\r\n this.lastWriteTime = Date.now();\r\n }\r\n\r\n /**\r\n * Check if messages should be grouped\r\n */\r\n protected get messagedShouldBeGrouped(): boolean {\r\n return Number(this.config(\"groupBy\")?.length) > 0;\r\n }\r\n\r\n /**\r\n * Write messages to the file\r\n */\r\n protected async writeMessagesToFile() {\r\n if (this.messages.length === 0 || this.isWriting || !this.isInitialized) return;\r\n\r\n this.isWriting = true;\r\n\r\n if (this.messagedShouldBeGrouped) {\r\n return await this.writeGroupedMessagesToFile();\r\n }\r\n\r\n await this.checkAndRotateFile(); // Ensure we check file size before writing\r\n\r\n try {\r\n await this.write(this.filePath, this.content);\r\n this.onSave();\r\n } catch (error) {\r\n console.error(\"Failed to write log:\", error);\r\n // Implement fallback logic here\r\n this.isWriting = false;\r\n }\r\n }\r\n\r\n /**\r\n * Write grouped messages to the file\r\n */\r\n protected async writeGroupedMessagesToFile(): Promise<void> {\r\n // first step, is to group the messages\r\n this.prepareGroupedMessages();\r\n\r\n // now each key in the grouped messages, represents the directory path that should extend the storage path\r\n for (const key in this.groupedMessages) {\r\n const directoryPath = path.join(this.storagePath, key);\r\n\r\n await ensureDirectoryAsync(directoryPath);\r\n\r\n const filePath = path.join(directoryPath, `${this.fileName}.${this.extension}`);\r\n\r\n await this.checkAndRotateFile(filePath); // Ensure we check file size before writing\r\n\r\n const content = this.groupedMessages[key].map((message) => message.content).join(EOL) + EOL;\r\n\r\n try {\r\n await this.write(filePath, content);\r\n } catch (error) {\r\n console.error(\"Failed to write log:\", error);\r\n }\r\n }\r\n\r\n this.onSave();\r\n this.isWriting = false;\r\n }\r\n\r\n /**\r\n * Prepare grouped messages\r\n */\r\n protected prepareGroupedMessages(): void {\r\n this.messages.forEach((message) => {\r\n const key = this.config(\"groupBy\")!\r\n .map((groupKey) => encodeURIComponent(message[groupKey]))\r\n .join(\"/\");\r\n\r\n this.groupedMessages[key] = this.groupedMessages[key] || [];\r\n this.groupedMessages[key].push(message);\r\n });\r\n }\r\n\r\n /**\r\n * Start writing to the file\r\n */\r\n protected async write(filePath: string, content: string) {\r\n return new Promise((resolve, reject) => {\r\n const writer = fs.createWriteStream(filePath, { flags: \"a\" });\r\n\r\n writer.write(content, (error) => {\r\n writer.end();\r\n if (error) {\r\n reject(error);\r\n } else {\r\n resolve(true);\r\n }\r\n });\r\n });\r\n }\r\n}\r\n"],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { LogContract, LoggingData } from "../types.mjs";
|
|
2
|
+
import { FileLog } from "./file-log.mjs";
|
|
3
|
+
|
|
4
|
+
//#region ../../@warlock.js/logger/src/channels/json-file-log.d.ts
|
|
5
|
+
declare class JSONFileLog extends FileLog implements LogContract {
|
|
6
|
+
/**
|
|
7
|
+
* {@inheritdoc}
|
|
8
|
+
*/
|
|
9
|
+
name: string;
|
|
10
|
+
/**
|
|
11
|
+
* Get file extension
|
|
12
|
+
*/
|
|
13
|
+
get extension(): string;
|
|
14
|
+
/**
|
|
15
|
+
* Synchronously flush messages
|
|
16
|
+
*/
|
|
17
|
+
flushSync(): void;
|
|
18
|
+
/**
|
|
19
|
+
* {@inheritdoc}
|
|
20
|
+
*/
|
|
21
|
+
log(data: LoggingData): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Write messages to the file
|
|
24
|
+
*/
|
|
25
|
+
protected writeMessagesToFile(): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Write grouped messages to the file
|
|
28
|
+
*/
|
|
29
|
+
protected writeGroupedMessagesToFile(): Promise<void>;
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
export { JSONFileLog };
|
|
33
|
+
//# sourceMappingURL=json-file-log.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-file-log.d.mts","names":[],"sources":["../../../../../../@warlock.js/logger/src/channels/json-file-log.ts"],"mappings":";;;;cAQa,WAAA,SAAoB,OAAA,YAAmB,WAAA;;AAApD;;EAIS,IAAA;EAuDgB;;;EAAA,IAlDZ,SAAA,CAAA;EAToB;;;EAgBxB,SAAA,CAAA;EAhBwB;;;EA2DlB,GAAA,CAAI,IAAA,EAAM,WAAA,GAAW,OAAA;EA3C3B;;;EAAA,UA4ES,mBAAA,CAAA,GAAuB,OAAA;EAjCL;;;EAAA,UAyElB,0BAAA,CAAA,GAA8B,OAAA;AAAA"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { FileLog } from "./file-log.mjs";
|
|
2
|
+
import { safeJsonStringify } from "../utils/safe-json-stringify.mjs";
|
|
3
|
+
import { ensureDirectoryAsync, fileExistsAsync, getJsonFileAsync } from "@warlock.js/fs";
|
|
4
|
+
import dayjs from "dayjs";
|
|
5
|
+
import fs from "fs";
|
|
6
|
+
import path from "path";
|
|
7
|
+
|
|
8
|
+
//#region ../../@warlock.js/logger/src/channels/json-file-log.ts
|
|
9
|
+
var JSONFileLog = class extends FileLog {
|
|
10
|
+
constructor(..._args) {
|
|
11
|
+
super(..._args);
|
|
12
|
+
this.name = "fileJson";
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Get file extension
|
|
16
|
+
*/
|
|
17
|
+
get extension() {
|
|
18
|
+
return "json";
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Synchronously flush messages
|
|
22
|
+
*/
|
|
23
|
+
flushSync() {
|
|
24
|
+
if (this.messages.length === 0 && Object.keys(this.groupedMessages).length === 0) return;
|
|
25
|
+
if (this.messagedShouldBeGrouped) {
|
|
26
|
+
this.prepareGroupedMessages();
|
|
27
|
+
for (const key in this.groupedMessages) {
|
|
28
|
+
const directoryPath = path.join(this.storagePath, key);
|
|
29
|
+
fs.mkdirSync(directoryPath, { recursive: true });
|
|
30
|
+
const filePath = path.join(directoryPath, `${this.fileName}.${this.extension}`);
|
|
31
|
+
let fileContents = { messages: [] };
|
|
32
|
+
if (fs.existsSync(filePath)) try {
|
|
33
|
+
fileContents = JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
34
|
+
if (!Array.isArray(fileContents.messages)) fileContents.messages = [];
|
|
35
|
+
} catch (e) {
|
|
36
|
+
fileContents = { messages: [] };
|
|
37
|
+
}
|
|
38
|
+
fileContents.messages.push(...this.groupedMessages[key]);
|
|
39
|
+
fs.writeFileSync(filePath, safeJsonStringify(fileContents, 2));
|
|
40
|
+
}
|
|
41
|
+
} else {
|
|
42
|
+
fs.mkdirSync(this.storagePath, { recursive: true });
|
|
43
|
+
let fileContents = { messages: [] };
|
|
44
|
+
if (fs.existsSync(this.filePath)) try {
|
|
45
|
+
fileContents = JSON.parse(fs.readFileSync(this.filePath, "utf-8"));
|
|
46
|
+
if (!Array.isArray(fileContents.messages)) fileContents.messages = [];
|
|
47
|
+
} catch (e) {
|
|
48
|
+
fileContents = { messages: [] };
|
|
49
|
+
}
|
|
50
|
+
fileContents.messages.push(...this.messages);
|
|
51
|
+
fs.writeFileSync(this.filePath, safeJsonStringify(fileContents, 2));
|
|
52
|
+
}
|
|
53
|
+
this.onSave();
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* {@inheritdoc}
|
|
57
|
+
*/
|
|
58
|
+
async log(data) {
|
|
59
|
+
let stack;
|
|
60
|
+
if (data.message instanceof Error) {
|
|
61
|
+
stack = data.message.stack?.split("\n");
|
|
62
|
+
data.message = data.message.message;
|
|
63
|
+
}
|
|
64
|
+
const { module, action, message, type: level, context } = data;
|
|
65
|
+
if (!this.shouldBeLogged(data)) return;
|
|
66
|
+
const { date: dateFormat, time } = this.getDateAndTimeFormat();
|
|
67
|
+
const date = dayjs().format(dateFormat + " " + time);
|
|
68
|
+
this.messages.push({
|
|
69
|
+
content: message,
|
|
70
|
+
level,
|
|
71
|
+
date,
|
|
72
|
+
module,
|
|
73
|
+
action,
|
|
74
|
+
stack,
|
|
75
|
+
context,
|
|
76
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
77
|
+
});
|
|
78
|
+
await this.checkIfMessagesShouldBeWritten();
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Write messages to the file
|
|
82
|
+
*/
|
|
83
|
+
async writeMessagesToFile() {
|
|
84
|
+
if (this.messages.length === 0 || this.isWriting || !this.isInitialized) return;
|
|
85
|
+
this.isWriting = true;
|
|
86
|
+
if (this.messagedShouldBeGrouped) return await this.writeGroupedMessagesToFile();
|
|
87
|
+
await this.checkAndRotateFile();
|
|
88
|
+
let fileContents = { messages: [] };
|
|
89
|
+
if (await fileExistsAsync(this.filePath)) try {
|
|
90
|
+
fileContents = await getJsonFileAsync(this.filePath);
|
|
91
|
+
} catch (error) {
|
|
92
|
+
console.error("Error reading log file, reinitializing:", error);
|
|
93
|
+
fileContents = { messages: [] };
|
|
94
|
+
}
|
|
95
|
+
else fileContents = { messages: [] };
|
|
96
|
+
fileContents.messages.push(...this.messages);
|
|
97
|
+
try {
|
|
98
|
+
await fs.promises.writeFile(this.filePath, safeJsonStringify(fileContents, 2));
|
|
99
|
+
this.onSave();
|
|
100
|
+
} catch (error) {
|
|
101
|
+
console.error("Failed to write log:", error);
|
|
102
|
+
this.isWriting = false;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Write grouped messages to the file
|
|
107
|
+
*/
|
|
108
|
+
async writeGroupedMessagesToFile() {
|
|
109
|
+
this.prepareGroupedMessages();
|
|
110
|
+
for (const key in this.groupedMessages) {
|
|
111
|
+
const directoryPath = path.join(this.storagePath, key);
|
|
112
|
+
await ensureDirectoryAsync(directoryPath);
|
|
113
|
+
const filePath = path.join(directoryPath, `${this.fileName}.${this.extension}`);
|
|
114
|
+
await this.checkAndRotateFile(filePath);
|
|
115
|
+
let fileContents = { messages: [] };
|
|
116
|
+
if (await fileExistsAsync(filePath)) try {
|
|
117
|
+
fileContents = await getJsonFileAsync(filePath);
|
|
118
|
+
} catch (error) {
|
|
119
|
+
console.error("Error reading log file, reinitializing:", error);
|
|
120
|
+
fileContents = { messages: [] };
|
|
121
|
+
}
|
|
122
|
+
else fileContents = { messages: [] };
|
|
123
|
+
fileContents.messages.push(...this.groupedMessages[key]);
|
|
124
|
+
try {
|
|
125
|
+
await fs.promises.writeFile(filePath, safeJsonStringify(fileContents, 2));
|
|
126
|
+
} catch (error) {
|
|
127
|
+
console.error("Failed to write log:", error);
|
|
128
|
+
this.isWriting = false;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
this.onSave();
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
//#endregion
|
|
136
|
+
export { JSONFileLog };
|
|
137
|
+
//# sourceMappingURL=json-file-log.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-file-log.mjs","names":[],"sources":["../../../../../../@warlock.js/logger/src/channels/json-file-log.ts"],"sourcesContent":["import { ensureDirectoryAsync, fileExistsAsync, getJsonFileAsync } from \"@warlock.js/fs\";\r\nimport dayjs from \"dayjs\";\r\nimport fs from \"fs\";\r\nimport path from \"path\";\r\nimport type { LogContract, LogMessage, LoggingData } from \"../types\";\r\nimport { safeJsonStringify } from \"../utils/safe-json-stringify\";\r\nimport { FileLog } from \"./file-log\";\r\n\r\nexport class JSONFileLog extends FileLog implements LogContract {\r\n /**\r\n * {@inheritdoc}\r\n */\r\n public name = \"fileJson\";\r\n\r\n /**\r\n * Get file extension\r\n */\r\n public get extension(): string {\r\n return \"json\";\r\n }\r\n\r\n /**\r\n * Synchronously flush messages\r\n */\r\n public flushSync(): void {\r\n if (this.messages.length === 0 && Object.keys(this.groupedMessages).length === 0) return;\r\n\r\n if (this.messagedShouldBeGrouped) {\r\n this.prepareGroupedMessages();\r\n for (const key in this.groupedMessages) {\r\n const directoryPath = path.join(this.storagePath, key);\r\n fs.mkdirSync(directoryPath, { recursive: true });\r\n const filePath = path.join(directoryPath, `${this.fileName}.${this.extension}`);\r\n\r\n let fileContents = { messages: [] as any[] };\r\n if (fs.existsSync(filePath)) {\r\n try {\r\n fileContents = JSON.parse(fs.readFileSync(filePath, \"utf-8\"));\r\n if (!Array.isArray(fileContents.messages)) fileContents.messages = [];\r\n } catch (e) {\r\n fileContents = { messages: [] };\r\n }\r\n }\r\n fileContents.messages.push(...this.groupedMessages[key]);\r\n fs.writeFileSync(filePath, safeJsonStringify(fileContents, 2));\r\n }\r\n } else {\r\n fs.mkdirSync(this.storagePath, { recursive: true });\r\n let fileContents = { messages: [] as any[] };\r\n if (fs.existsSync(this.filePath)) {\r\n try {\r\n fileContents = JSON.parse(fs.readFileSync(this.filePath, \"utf-8\"));\r\n if (!Array.isArray(fileContents.messages)) fileContents.messages = [];\r\n } catch (e) {\r\n fileContents = { messages: [] };\r\n }\r\n }\r\n fileContents.messages.push(...this.messages);\r\n fs.writeFileSync(this.filePath, safeJsonStringify(fileContents, 2));\r\n }\r\n\r\n this.onSave();\r\n }\r\n\r\n /**\r\n * {@inheritdoc}\r\n */\r\n public async log(data: LoggingData) {\r\n let stack: string[] | undefined;\r\n\r\n if (data.message instanceof Error) {\r\n stack = data.message.stack?.split(\"\\n\");\r\n data.message = data.message.message;\r\n }\r\n\r\n const { module, action, message, type: level, context } = data;\r\n\r\n if (!this.shouldBeLogged(data)) return;\r\n\r\n const { date: dateFormat, time } = this.getDateAndTimeFormat();\r\n\r\n const date = dayjs().format(dateFormat + \" \" + time);\r\n\r\n this.messages.push({\r\n content: message,\r\n level,\r\n date,\r\n module,\r\n action,\r\n stack,\r\n context,\r\n timestamp: new Date().toISOString(),\r\n } as LogMessage);\r\n\r\n await this.checkIfMessagesShouldBeWritten(); // Immediate check on buffer size\r\n }\r\n\r\n /**\r\n * Write messages to the file\r\n */\r\n protected async writeMessagesToFile(): Promise<void> {\r\n if (this.messages.length === 0 || this.isWriting || !this.isInitialized) return;\r\n\r\n this.isWriting = true;\r\n\r\n if (this.messagedShouldBeGrouped) {\r\n return await this.writeGroupedMessagesToFile();\r\n }\r\n\r\n await this.checkAndRotateFile(); // Ensure file rotation is handled\r\n\r\n let fileContents = { messages: [] as any[] };\r\n\r\n if (await fileExistsAsync(this.filePath)) {\r\n try {\r\n fileContents = (await getJsonFileAsync(this.filePath)) as { messages: any[] };\r\n } catch (error) {\r\n console.error(\"Error reading log file, reinitializing:\", error);\r\n fileContents = { messages: [] }; // Reinitialize the file if corrupted\r\n }\r\n } else {\r\n fileContents = { messages: [] }; // Reinitialize the file if corrupted\r\n }\r\n\r\n fileContents.messages.push(...this.messages);\r\n\r\n try {\r\n await fs.promises.writeFile(this.filePath, safeJsonStringify(fileContents, 2));\r\n\r\n this.onSave();\r\n } catch (error) {\r\n console.error(\"Failed to write log:\", error);\r\n // Implement fallback logic here\r\n this.isWriting = false;\r\n }\r\n }\r\n\r\n /**\r\n * Write grouped messages to the file\r\n */\r\n protected async writeGroupedMessagesToFile(): Promise<void> {\r\n // first step, is to group the messages\r\n this.prepareGroupedMessages();\r\n\r\n // now each key in the grouped messages, represents the directory path that should extend the storage path\r\n for (const key in this.groupedMessages) {\r\n const directoryPath = path.join(this.storagePath, key);\r\n\r\n await ensureDirectoryAsync(directoryPath);\r\n\r\n const filePath = path.join(directoryPath, `${this.fileName}.${this.extension}`);\r\n\r\n await this.checkAndRotateFile(filePath); // Ensure we check file size before writing\r\n\r\n let fileContents: { messages: any[] } = { messages: [] };\r\n if (await fileExistsAsync(filePath)) {\r\n try {\r\n fileContents = (await getJsonFileAsync(filePath)) as { messages: any[] };\r\n } catch (error) {\r\n console.error(\"Error reading log file, reinitializing:\", error);\r\n fileContents = { messages: [] };\r\n }\r\n } else {\r\n fileContents = { messages: [] };\r\n }\r\n\r\n fileContents.messages.push(...this.groupedMessages[key]);\r\n\r\n try {\r\n await fs.promises.writeFile(filePath, safeJsonStringify(fileContents, 2));\r\n } catch (error) {\r\n console.error(\"Failed to write log:\", error);\r\n this.isWriting = false;\r\n }\r\n }\r\n\r\n this.onSave();\r\n }\r\n}\r\n"],"mappings":"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"}
|
package/esm/index.d.mts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { AutoFlushEvent, BasicLogConfigurations, DebugMode, LogContract, LogLevel, LogMessage, LoggingData, OmittedLoggingData, RedactCensor, RedactConfig } from "./types.mjs";
|
|
2
|
+
import { LogChannel } from "./log-channel.mjs";
|
|
3
|
+
import { ConsoleLog, ConsoleLogConfig } from "./channels/console-log.mjs";
|
|
4
|
+
import { FileLog, FileLogConfig } from "./channels/file-log.mjs";
|
|
5
|
+
import { JSONFileLog } from "./channels/json-file-log.mjs";
|
|
6
|
+
import { Logger, log } from "./logger.mjs";
|
|
7
|
+
import { applyRedact, mergeRedact } from "./redact/redact.mjs";
|
|
8
|
+
import { captureAnyUnhandledRejection } from "./utils/capture-unhandled-errors.mjs";
|
|
9
|
+
import { clearMessage } from "./utils/clear-message.mjs";
|
|
10
|
+
import { safeJsonStringify } from "./utils/safe-json-stringify.mjs";
|
|
11
|
+
export { AutoFlushEvent, BasicLogConfigurations, ConsoleLog, ConsoleLogConfig, DebugMode, FileLog, FileLogConfig, JSONFileLog, LogChannel, LogContract, LogLevel, LogMessage, Logger, LoggingData, OmittedLoggingData, RedactCensor, RedactConfig, applyRedact, captureAnyUnhandledRejection, clearMessage, log, mergeRedact, safeJsonStringify };
|
package/esm/index.mjs
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { LogChannel } from "./log-channel.mjs";
|
|
2
|
+
import { ConsoleLog } from "./channels/console-log.mjs";
|
|
3
|
+
import { FileLog } from "./channels/file-log.mjs";
|
|
4
|
+
import { safeJsonStringify } from "./utils/safe-json-stringify.mjs";
|
|
5
|
+
import { JSONFileLog } from "./channels/json-file-log.mjs";
|
|
6
|
+
import "./channels/index.mjs";
|
|
7
|
+
import { applyRedact, mergeRedact } from "./redact/redact.mjs";
|
|
8
|
+
import { clearMessage } from "./utils/clear-message.mjs";
|
|
9
|
+
import { Logger, log } from "./logger.mjs";
|
|
10
|
+
import { captureAnyUnhandledRejection } from "./utils/capture-unhandled-errors.mjs";
|
|
11
|
+
import "./utils/index.mjs";
|
|
12
|
+
|
|
13
|
+
export { ConsoleLog, FileLog, JSONFileLog, LogChannel, Logger, applyRedact, captureAnyUnhandledRejection, clearMessage, log, mergeRedact, safeJsonStringify };
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { BasicLogConfigurations, LogContract, LoggingData, RedactConfig } from "./types.mjs";
|
|
2
|
+
|
|
3
|
+
//#region ../../@warlock.js/logger/src/log-channel.d.ts
|
|
4
|
+
declare abstract class LogChannel<Options extends BasicLogConfigurations = BasicLogConfigurations> implements LogContract {
|
|
5
|
+
/**
|
|
6
|
+
* Channel name
|
|
7
|
+
*/
|
|
8
|
+
name: string;
|
|
9
|
+
/**
|
|
10
|
+
* Channel description
|
|
11
|
+
*/
|
|
12
|
+
description?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Determine if channel is logging in terminal
|
|
15
|
+
*/
|
|
16
|
+
terminal: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Default Configurations
|
|
19
|
+
*/
|
|
20
|
+
protected defaultConfigurations: Options;
|
|
21
|
+
/**
|
|
22
|
+
* Channel configurations
|
|
23
|
+
*/
|
|
24
|
+
protected channelConfigurations: Options;
|
|
25
|
+
/**
|
|
26
|
+
* Determine whether the channel is fully initialized
|
|
27
|
+
*/
|
|
28
|
+
protected isInitialized: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Constructor
|
|
31
|
+
*/
|
|
32
|
+
constructor(configurations?: Options);
|
|
33
|
+
/**
|
|
34
|
+
* Initialize the channel
|
|
35
|
+
*/
|
|
36
|
+
protected init?(): void | Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Get config value
|
|
39
|
+
*/
|
|
40
|
+
protected config<K extends keyof Options>(key: K): Options[K];
|
|
41
|
+
/**
|
|
42
|
+
* Set configurations
|
|
43
|
+
*/
|
|
44
|
+
protected setConfigurations(configurations: Options): this;
|
|
45
|
+
/**
|
|
46
|
+
* Determine if the message should be logged
|
|
47
|
+
*/
|
|
48
|
+
protected shouldBeLogged(data: LoggingData): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Log the given message
|
|
51
|
+
*/
|
|
52
|
+
abstract log(data: LoggingData): void | Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* Synchronously flush messages
|
|
55
|
+
*/
|
|
56
|
+
flushSync?(): void;
|
|
57
|
+
/**
|
|
58
|
+
* Read the channel's redact config (if any). Used by `Logger` to apply
|
|
59
|
+
* per-channel additive redaction on top of the logger-wide floor.
|
|
60
|
+
* Subclasses normally don't override this — set `redact` in your channel
|
|
61
|
+
* configuration instead.
|
|
62
|
+
*/
|
|
63
|
+
getRedactConfig(): RedactConfig | undefined;
|
|
64
|
+
/**
|
|
65
|
+
* Get date and time formats
|
|
66
|
+
*/
|
|
67
|
+
protected getDateAndTimeFormat(): {
|
|
68
|
+
date: string;
|
|
69
|
+
time: string;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* get basic configurations with the given ones
|
|
73
|
+
*/
|
|
74
|
+
protected withBasicConfigurations(configurations: Partial<Options>): Options;
|
|
75
|
+
}
|
|
76
|
+
//#endregion
|
|
77
|
+
export { LogChannel };
|
|
78
|
+
//# sourceMappingURL=log-channel.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-channel.d.mts","names":[],"sources":["../../../../../@warlock.js/logger/src/log-channel.ts"],"mappings":";;;uBAOsB,UAAA,iBACJ,sBAAA,GAAyB,sBAAA,aAC9B,WAAA;;AAFb;;EAOS,IAAA;EANS;;;EAWT,WAAA;EAyB6B;;;EApB7B,QAAA;EA0C4C;;;EAAA,UArCzC,qBAAA,EAAuB,OAAA;EA6EP;;;EAAA,UAxEhB,qBAAA,EAAuB,OAAA;EAyGiB;;;EAAA,UApGxC,aAAA;EA9BY;;;cAmCH,cAAA,GAAiB,OAAA;EAnCzB;;;EAAA,UAoDD,IAAA,CAAA,CAAA,UAAgB,OAAA;EAhChB;;;EAAA,UAqCA,MAAA,iBAAuB,OAAA,CAAA,CAAS,GAAA,EAAK,CAAA,GAAI,OAAA,CAAQ,CAAA;EA3BjD;;;EAAA,UAoCA,iBAAA,CAAkB,cAAA,EAAgB,OAAA;EAdlC;;;EAAA,UA0BA,cAAA,CAAe,IAAA,EAAM,WAAA;EArBE;;;EAAA,SAwCjB,GAAA,CAAI,IAAA,EAAM,WAAA,UAAqB,OAAA;EAxCY;;;EA6CpD,SAAA,CAAA,CAAA;EAxBG;;;;;;EAgCH,eAAA,CAAA,GAAmB,YAAA;EARnB;;;EAAA,UAiBG,oBAAA,CAAA;;;;EAWwC;;;EAAA,UAAxC,uBAAA,CAAwB,cAAA,EAAgB,OAAA,CAAQ,OAAA,IAAW,OAAA;AAAA"}
|